Възможно ли е да използвам go1.11 за да компилирам програма от 2012г.? Защо?
Какъв тип връша main функцията?
Можем ли да дефинираме променлива без да пишем тима излишно?
Да - чрез type inference
a := 42 b := "a string"
Не можем да го ползваме в глобалния скоуп
Как се import-ва пакет, публикуван публично в gitlab?
import "gitlab.com/user/awesomepack"
Какъв е идиоматичния начин за правене на enum в Go?
За какво се използва iota
в Go и коя подред буква в гръцката азбука е?
iota
const ( City = iota Town Village )
Мъфините съдържат
note: Не сме секта.
Сладкия Gopher е създаден от Renée French. Той е централна причина за успеха на езика.
1. Функции
2. Ламбди
3. Методи
package main import ( "fmt" "strings" ) func ping() { fmt.Println("pong") } func myprint(s string) { fmt.Println(s) } func shout(s string) string { return strings.ToUpper(s) + "!!!1!" } func main() { ping() myprint("woot") myprint(shout("woot")) }
func foo(a int, b string) float64
Функцията foo приема int и string и връща float64
Когато няколко аргумента са от един тип:
func bar(a, b int, c float64) float64
func sum(args ...int) int
Функцията sum приема произволен брой числа и връща техния сбор
func sum(args ...int) int { result := 0 for _, v := range args { result += v } return result }
Извикваме я с колкото ни трябват
sum() //0 sum(2, 3) //5 sum(2, 3, 4, 5) //14
Трябва да е последния аргумент на функцията
* Следващия път ще говорим по-подробно за range
package main import "fmt" func main() { sum, count := sumAndCount(2, 3, 4, 5) fmt.Println("Резултатът от sumAndCount() е", sum, count) } func sumAndCount(args ...int) (int, int) { result := 0 for _, v := range args { result += v } return result, len(args) }
1. Знаем, че ако дефинираме променлива и не я използваме, гърми
2. Ако искаме онзи сбор и не ни интересува броят аргументи, това ще изгърми
result, count := sumAndCount(2, 3, 4, 5)
3. Ако нямаме нужда от дадена стойност, я присвояваме на _:
result, _ := sumAndCount(2, 3, 4, 5)
func sumAndCount(args ...int) (result int, count int) { count = len(args) for _, v := range args { result += v } return }
func foo(bar func(int, float64) float64) float64 { return bar(5, 3.2) }
func createRandomGenerator() func() int { return func() int { return 4 } }
nil
package main
import "fmt"
func main() {
fmt.Println("factorial(5) returns:")
fmt.Println(factorial(5))
}
func factorial(x uint) uint { if x == 0 { return 1 } return x * factorial(x-1) }
ЗнаетеЛиЧеHelloWorldНаКитайскиЕ世界
е валидно име на функцияfunc(x, y int) int { return x * y }
package main
import "fmt"
func main() { add := func(x, y int) int { return x + y } fmt.Println(add(4, 5)) fmt.Println(func(x, y int) int { return x + y }(3, 8)) }
package main import "fmt" func counter(start int) func() int { count := start return func() int { count++ return count } } func main() { c := counter(3) fmt.Println("The first 3 values are", c(), c(), c()) }
Променливата count
нужна ли е въобще?
defer
е специален механизъм на езикаdefer
добавя извикване на функция в един списък (стек)package main
import "fmt"
func main() { fmt.Println("counting") for i := 0; i < 10; i++ { defer fmt.Println(i) } fmt.Println("done") }
func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } dst, err := os.Create(dstName) if err != nil { return } written, err = io.Copy(dst, src) dst.Close() src.Close() return }
Какви са проблемите с този код?
func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } defer src.Close() dst, err := os.Create(dstName) if err != nil { return } defer dst.Close() return io.Copy(dst, src) }
defer
се използва за сигурно и лесно почистване на ресурси (отворени файлове, заключени mutex-и
, etc.)
defer
statement-ите ни позволяват да мислим за затварянето на файловете веднага след отварянето имdefer
се оценяват, когато самият defer
statement се оценяваfunc a() { i := 0 defer fmt.Println(i) i++ return }
LIFO
редfunc b() { for i := 0; i < 4; i++ { defer fmt.Print(i) } }
defer
-натите функции могат да "пипат" по именованите връщани аргументи на обграждащата функцияfunc c() (i int) { defer func() { i++ }() return 1 }
package main
import (
"fmt"
)
func deferExample() { for i := 0; i < 5; i++ { defer func(i int) { fmt.Printf(" %v", i) }(i) } }
func main() {
deferExample()
}
-
package main
import (
"fmt"
)
func deferExample() { for i := 0; i < 5; i++ { defer func() { fmt.Printf(" %v", i) }() } }
func main() {
deferExample()
}
За тях ще си говорим като стигнем до дефиниране на типове
&
*int
intP == *(&intP)
package main import "fmt" var ( name string = "Чочко" age uint8 = 27 pName *string ) func main() { pName = &name fmt.Printf("name е на адрес %p и има стойност %s\n", pName, name) fmt.Printf("age е на адрес %p и има стойност %d\n", &age, age) }
package main func main() { var p *int = nil *p = 0 }
func foo(a int, b *string) float64
Функцията foo приема int и указател към string и връща float64
Демек a
бива копиран в скоупа на foo
, а b
просто сочи към някаква стойност отвън.
b
не се копира. Ако в него има около 652183859 символа*, това е предимствоa
не влияе на нищо извън тази функцияb
променяме оригиналната стойност*Следващия път ще видим защо указател към string може да не ни спести кой-знае колко памет