archive tar zip bufio builtin bytes compress bzip2 flate gzip lzw zlib
container heap list ring crypto aes cipher des dsa ecdsa elliptic hmac
md5 rand rc4 rsa sha1 sha256 sha512 subtle tls x509 pkix database sql
driver debug dwarf elf gosym macho pe plan9obj encoding ascii85 asn1
base32 base64 binary csv gob hex json pem xml errors expvar flag fmt
go ast build constant doc format importer parser printer scanner token
types hash adler32 crc32 crc64 fnv html template image color palette
draw gif jpeg png index suffixarray io ioutil log syslog math big cmplx
rand mime multipart quotedprintable net http cgi cookiejar fcgi httptest
httputil pprof mail rpc jsonrpc smtp textproto url os exec signal user
path filepath reflect regexp syntax runtime cgo debug pprof race trace
sort strconv strings sync atomic syscall testing iotest quick text
scanner tabwriter template parse time unicode utf16 utf8 unsafe
package workq type Queue []*Item func (q *Queue) Push(item *Item) { *q = append(*q, item) go item.Translate() } func (q *Queue) Pop() *Item { if !q.IsEmpty() { old := *q item := old[0] <- item.Done *q = old[1:len(old)] return item } return nil } func (q *Queue) Len() int { return len(*q) }
* Linux, FreeBSD
Инсталирате си пакета go
от вашия пакетен мениджър
* Mac OSX
Използвате симпатичния инсталатор
* Windows
Използвате симпатичния инсталатор
По време на курса ще използваме версия 1.5.1
1. Създавате директория ~/go
2. Слагате следните два реда в ~/.profile
export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin
* За Windows-аджийте има уловки:
C:\Go
вместо вас и можете да ползвате неяЗа да сме сигурни, че сме направили всичко като хората, създаваме файл hello.go:
package main import "fmt" func main() { fmt.Printf("Hello, world!\n") }
и изпълняваме
go run hello.go
Ако всичко изглежда наред, правим скрийншот и получаваме точка :)
Имаме инструментът go
, който се грижи за достатъчно много неща.
Повечето настройки се правят с environment variables
.
workspace
, с три основни директории:
src
съдържа нашия сорс код, който е организиран в пакети (за тях след малко)pkg
съдържа т.нар. package objects
bin
съдържа компилираните ни програмиbuild compile packages and dependencies clean remove object files doc show documentation for package or symbol env print Go environment information fix run go tool fix on packages fmt run gofmt on package sources generate generate Go files by processing source get download and install packages and dependencies install compile and install packages and dependencies list list packages run compile and run Go program test test packages tool run specified go tool version print Go version vet run go tool vet on packages
$ go env GOARCH="amd64" GOBIN="" GOEXE="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOOS="linux" GOPATH="/home/user/go" GORACE="" GOROOT="/usr/lib/go" GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64" GO15VENDOREXPERIMENT="" CC="gcc" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0" CXX="g++" CGO_ENABLED="1"`
bin/ streak # command executable pkg/ linux_amd64/ code.google.com/p/goauth2/ oauth.a # package object src/ code.google.com/p/goauth2/ .hg/ # mercurial repository metadata oauth/ oauth.go # package source oauth_test.go # test source github.com/nf/ streak/ .git/ # git repository metadata oauth.go # command source streak.go # command source
Връщаме се обратно към Hello, world! примера:
package main import "fmt" func main() { fmt.Printf("Hello, world!\n") }
и се фокусираме върху
package main
Една програма на Go
е структура от пакети. Нямате шанс просто да хвърлите
едно парче код, в даден файл и то да тръгне.
n
файла могат да са в един пакет (демек filename
!= package
)fmt
, os
...Без значение от колко файла се състои:
Ако си мислите за "Lord of the rings", грешите. Говорим ви за main
.
В една програма имаме точно един пакет main
и при изпълнението ѝ се изпълнява функцията main
в него.
Програмата приключва, когато приключи изпълнението на функцията main
.
Тя не връща нищо.
Става с ключовата думичка import
, последвана от името на пакета, в кавички
import "fmt"
Ако искаме да импортнем няколко пакета:
import "fmt" import "os"
което go fmt би свел до
import ( "fmt" "os" )
package main import ( "fmt" "os" ) func main() { fmt.Printf("Hello, world!\n") }
Какво точно можем да използваме от импортнат пакет? Тук става забавно.
Даден идентификатор (било то на променлива, константа, тип, функция или
метод) е видим извън пакета си, тогава и само тогава когато името му започва с главна буква.
Наричаме ги exported
(на други места им викат public
).
Останалите са недостъпни (демек private
)
Имаме свободата да решим точно колко байта да е нашия тип:
... и разбира се имаме unsigned
:
uint
и int
uintptr
- нещо достатъчно голямо за да съдържа битовете на указател
Типовете int
и int32
са различни дори в архитектури на които int
е 32 бита. Същото е и за uint
.
var name string = "Чочко Чочков" var age uint8 = 25
Горното можем (и трябва) да запишем като:
var ( name string = "Чочко Чочков" age uint8 = 25 )
Ако са с един и същи тип, можем и така:
var name, age string = "Чочко Чочков", "двадесет и пет"
WTF! WTF! WTF! Защо типа е на грешното място!?
Можем да правим и така:
name := "Чочко Чочков" age := 25
package main import "fmt" name := "Киро" func main() { fmt.Printf("%s, защо да не може?\n", name) }
Не се грижим за това да си инициализираме стойностите. Всяка променлива в Go се инициализира по подразбиране:
var ( digit int // 0 digit *int // nil number float64 // 0.0 isIt bool // false name string // "" root complex64 // (0+0i) pipe chan <type> // nil )
Кастването работи, както очаквате:
number := 42 // (int=42.0) specificNumber := float64(number) // (float64=42.0)
С тази разлика, че нямате имплицитен каст:
number * specificNumber // (mismatched types int and float64)
Дефинирана стойност, която не се използва, води до грешка по време на компилация
package main import "fmt" func main() { name := "Кевин" fmt.Printf("Май забравихме някой?\n") }
Аналогично с var:
const ( name string = "Чочко Чочков" age uint8 = 25 )
Могат да бъдат само
Нали помните enum
?
const ( Monday = iota Tuesday Wednesday Thursday Friday Partyday Sunday )
if age < 13 { fmt.Print("Още не си тийнейджър") } else if age >= 13 && age < 20 { fmt.Print("В момента си тийнейджър") } else { fmt.Print("Минали са ти тийнейджърските години") }
(
и )
около условията{
е на същия ред с условието.} else {
трябва да са на един редelse if
, няма elseif
Добрия стар for
от C:
for i := 0; i < 20; i++ { fmt.Println(i) }
И точно както в C, някои от аргументите не са задължителни.
... някои да се чете като всички.
package main
import "fmt"
func main() {
for { fmt.Println("Can't stop me!") }
}
Забележка: Отварящата {
и тук е на същия ред с условието
Няма. for
покрива всичките му приложения.
Няма. for
покрива всичките му приложения.
switch { case age < 13: fmt.Print("Още не си тийнейджър") case age >= 13 && age < 20: fmt.Print("В момента си тийнейджър") default: fmt.Print("Минали са ти тийнейджърските години") }
Няма нужда от излишния break
Ако искаме да изпълним два поредни case-а
, използваме fallthrough
.
Все пак има break
, който е приложим за for
цикли.
continue
работи, точно както очаквате и където очаквате.
Да, има и такова.
Ако не знаете кога, не го ползвайте.
Към момента допускаме, че още не знаете кога => не го ползвате.
Q: Няма точка и запетая след всеки израз?
A: Всъщност има, но е имплицитна.
Сега си спомнете за правилото с отварящата {
.
Q: Интервали vs. Табове?
A: Един таб.
Q: Нещо за четене? Книги? Туториъли?
A: