基本是边看视频边做笔记。
视频地址
注意以上视频需要有safaribooks的账号才能收看。个人用户3000日元/月,
比那些月付成人视频网站性价比高多了。当然,我用的是公司买下的企业子账号。
:=
是什么
变量申明
变量赋值
1 2
| var my_var Int my_var = 1
|
申明并赋值
1 2 3 4
| var my_var = 1 // 或者 my_var := 1
|
由于已经赋初值,所以变量的类型可以省略。
另外注意 :=
的形式只能用在函数中。否则会出现类似
1
| expected declaration, found 'IDENT'
|
的编译错误提示。
变量的scope
在go中,外部scope中定义的变量可以在内部scope中access。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package main import "fmt" var my_var = "myvar" func main() { myscope() } func myscope() { fmt.Println(my_var) } #=> myvar
|
这点和Javascript类似。
1 2 3 4 5 6 7 8 9
| > var my_var = 1 undefined > function myfunc(){ ... console.log(my_var) ... } undefined > myfunc() 1 undefined
|
而在Ruby中,method内部是无法获取外部的变量值的。
1 2 3 4 5 6 7 8 9 10 11
| irb(main):001:0> my_var = "myvar" => "myvar" irb(main):002:0> def myfunc irb(main):003:1> print my_var irb(main):004:1> end => :myfunc irb(main):005:0> myfunc NameError: undefined local variable or method `my_var' for main:Object from (irb):3:in `myfunc' from (irb):5 from /Users/gyorou/.anyenv/envs/rbenv/versions/2.3.3/bin/irb:11:in `<main>'
|
在Ruby中,scope的边界取决于def
, class
, module
这类关键词。但是我们使用block来打开scope的边界。
1 2 3 4 5 6
| irb(main):009:0> define_method(:myfunc2) do irb(main):010:1* print my_var irb(main):011:1> end => :myfunc2 irb(main):012:0> myfunc2() myvar=> nil
|
iota
golang 的 Const常量中已经定义的递增的隐含变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package main import "fmt" const ( zero = iota one = iota two = iota three = iota ) func main() { fmt.Printf("zero:%v\n", zero) fmt.Printf("one:%v\n", one) fmt.Printf("two:%v\n", two) fmt.Printf("three:%v\n", two) } zero:0 one:1 two:2 three:3
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const ( January Month = 1 + iota February March April May June July August September October November December )
|
1 2 3 4 5 6 7 8 9
| const ( a0 = iota // 0 初始化 a1 // 1 a2 // 2 a3 = 10 a4 // 10 a5 = iota // 5(a3 a4 未使用iota,但是iota保持递增) a6 // 6 )
|
从中可以看到的规律是,下一个变量的默认值的计算公式总是和上一个变量相同,唯一变化的是下一个变量的iota会增加1。
array and slice
array 属于value, 而slice则是引用。
在go中array应用场景不多,尽量使用slice。
map
key 的顺序无法保证。如果我们要保证输出的顺序,则可以抽取所有的key生成array之后,排序,然后按照key来取相对的值。
type and interface
定义一个HttpRequest类型
1 2 3 4 5
| type HttpRequest struct { url string header map[string]string body string }
|
于是我们可以定义这个type的method。
1 2 3
| func (http *HttpRequest) GetBody() string { return http.body }
|
完整程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package main import "fmt" type HttpRequest struct { url string header map[string]string body string } func (http *HttpRequest) GetBody() string { return http.body } func main() { http := HttpRequest{"www.bocchi.tokyo", map[string]string{}, "fuck your mother"} fmt.Println(http.GetBody()) }
|
输出结果fuck your mother
。
对于任何type我们都可以定义method。
1 2 3 4
| type Hex int func (h Hex) String() string { return fmt.Sprintf("0x%x", int(h)) }
|
甚至函数也可以定义自己的method。
1 2 3 4
| type HandlerFunc func(w ResponseWriter, r *Request) func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
|
下面再看 interface
1 2 3
| type Handler interface { ServeHTTP(w ResponseWriter, r *Request) }
|
Golang中不需要明确指明我们的某个type实现了某个interface,我们只需要实现同名的method就行了。
例如上面,我们的HandlerFunc
类型就已经实现了handler
的interface,所以我们可以有如下的用法啦。
1 2 3 4 5 6
| f := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello, world") }) http.Handle("/", f)
|
更多参考