unsafe
при необходимостgo get -u golang.org/x/tools/cmd/present
archive tar zip bufio builtin bytes compress bzip2 flate gzip lzw zlib
container heap list ring context 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 bits cmplx rand mime multipart quotedprintable net
http cgi cookiejar fcgi httptest httptrace httputil pprof mail rpc jsonrpc smtp
textproto url os exec signal user path filepath plugin reflect regexp syntax
runtime cgo debug msan pprof race trace sort strconv strings sync atomic
syscall js 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.11.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 and cached files doc show documentation for package or symbol env print Go environment information bug start a bug report fix update packages to use new APIs fmt gofmt (reformat) 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 report likely mistakes in 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" CC="gcc" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0" CXX="g++" CGO_ENABLED="1"
bin/ hello # command executable outyet # command executable pkg/ linux_amd64/ github.com/golang/example/ stringutil.a # package object src/ github.com/golang/example/ .git/ # Git repository metadata hello/ hello.go # command source outyet/ main.go # command source main_test.go # test source golang.org/x/image/ .git/ # Git repository metadata bmp/ reader.go # package source writer.go # package source ... (many more repositories and packages omitted) ...
Връщаме се обратно към 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" )
имаме и такива магии:
import "github.com/keltia/leftpad"
wow! much import! how to dependency?
package main import ( "fmt" "os" ) func main() { fmt.Printf("Hello, world!\n") }
Какво точно можем да използваме от импортнат пакет? Тук става забавно.
Даден идентификатор (било то на променлива, константа, тип, функция или
метод) е видим извън пакета си, тогава и само тогава когато името му започва с главна буква.
Наричаме ги exported
(на други места им викат public
).
Останалите са недостъпни (демек private
)
Имаме свободата да решим точно колко байта да е нашия тип:
... и разбира се имаме unsigned
:
uint
и int
може да са 32 или 64 битаuintptr
- нещо достатъчно голямо за да съдържа битовете на указател
Пояснение: типовете int
и int32
са различни дори в архитектури на които int
е 32 бита. Същото важи и за uint
и uint32
.
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) }
Кастването работи, както очаквате:
number := 42 // (int=42) specificNumber := float64(number) // (float64=42.0)
С тази разлика, че нямате имплицитен каст:
package main func main() { number := 42 specificNumber := float64(number) println(number * specificNumber) // (mismatched types int and float64) }
rune
и се инициализира с единични кавички: 'a', 'ж', '本', '\u12e4'
package main import "fmt" func main() { fmt.Printf("We have a cool fmt package: %c %c!\n", '\u2713', '☢') fmt.Printf("こんにちは世界!\n") fmt.Printf(`With backticks we can ignore backslashes like \n!`) }
Не се грижим за това да си инициализираме стойностите. Всяка променлива в 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 )
init()
функцииpackage main import "fmt" var subject string func init() { subject = "world" } func main() { fmt.Printf("Hello, %s!\n", subject) }
За разлика от нормалните функции, за които ще си говорим следващия път, можем да имаме няколко init()
функции в един пакет
Дефинирана стойност, която не се използва, води до грешка по време на компилация
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 )
package main import "fmt" const ( B uint64 = iota + 1 KB = 1 << (10 * iota) MB GB TB ) func main() { fmt.Printf("Result is %d bytes", 2*KB) }
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: