安装
ubuntu
在官网下载源码go
这个下载地址被墙了,有点尴尬
windows
下载go:https://golang.org/doc/install
安装相关vscode相关插件: 需要设置代理
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
basic
export names: 所有需要导出的变量名均以大写开头
函数定义:变量名在前,类型在后。如果连续多个参数类型相同,可以只写一次
可以有多个返回值 返回值也可以直接定义变量名,此时return的时候不需要指定返回对象了
func add(x int, y int) int {
return x + y
}
go 中只有for循环,不需要写(),但一定要写{}
go 如果只写一个表达式,则等同于while
如果啥都不写,则是一个死循环
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
for sum < 1000 {
sum += sum
}
for {
}
go if 语句不需要(),必须有{}
if 语句可以定义临时表达式
if value = func(); value >10{
}
go 的switch语句自带break
defer 定义了一个在函数返回后执行的语句
如果定义了多个defer语句,那么通过栈的方式,last in first out
go 的指针可以直接通过.访问struct的成员
数组
var a[10] int
slices:不存数据,是array区间的引用
slices 的 len和 cap
nil slices len = 0, cap = 0
用make创建slice,创建指定长数组
a := make([]int, 5) // len(a)=5
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:] // len(b)=4, cap(b)=4
append 往slice中添加元素
range index ,value
pow := make([]int, 10)
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
go 的map
m = make(map[string]Vertex)
map插入、删除、访问、判断键值是否存在
m := make(map[string]int)
m["Answer"] = 42
fmt.Println("The value:", m["Answer"])
m["Answer"] = 48
fmt.Println("The value:", m["Answer"])
delete(m, "Answer")
fmt.Println("The value:", m["Answer"])
v, ok := m["Answer"]
fmt.Println("The value:", v, "Present?", ok)go
函数作为参数
func compute(fn func(float64, float64) float64) float64 {
return fn(3, 4)
}
func main() {
hypot := func(x, y float64) float64 {
return math.Sqrt(x*x + y*y)
}
fmt.Println(hypot(5, 12))
fmt.Println(compute(hypot))
fmt.Println(compute(math.Pow))
}
函数闭包
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
func main() {
pos, neg := adder(), adder()
for i := 0; i < 10; i++ {
fmt.Println(
pos(i),
neg(-2*i),
)
}
}
method
method 是function的一种
go 中没有类,但可以通过定义receiver method 实现类似成员函数的东西
pointer reciver: 会改变成员变量的值
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{3, 4}
fmt.Println(v.Abs())
}
Interfaces
An interface type is defined as a set of method signatures.
对象可隐式类型转换为Interfaces
访问nil interface没有意义,会出错
empty interface
Stringer , Error
Reader
channels
chan<- int
表示只发送的channel,不接收
<-chan int
表示只接收不发送的channel
不能close只接收的channel
- cap() 查看容量 capacity
- len() 获得长度
测试覆盖率
- go tool cover
Goroutines
Buffered Channels
当channel的buffer满了,会产生阻塞
range and close 判断一个channel是否已关闭
change 的 for range:循环取值,直到channel 关闭
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
select 语句监听多个 channel,阻塞直到某一个channel有数据,并执行那个channel
如果同时有多个channel,则随机执行一个
default select 如果select没有满足条件的,那么可以执行default
sync.Mutex Lock Unlock
sync.WaitGroup
package main
import (
"fmt"
"golang.org/x/tour/tree"
)
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int) {
WalkAux(t, ch)
close(ch)
}
func WalkAux(t *tree.Tree, ch chan int) {
if t != nil {
WalkAux(t.Left, ch)
ch <- t.Value
WalkAux(t.Right, ch)
}
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
ch1 := make(chan int)
ch2 := make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for {
v1, s1 := <-ch1
v2, s2 := <-ch2
if s1 != s2 || v1 != v2 {
return false
}
if s1 == false {
break
}
}
return true
}
func main() {
fmt.Println(Same(tree.New(1), tree.New(2)))
fmt.Println(Same(tree.New(1), tree.New(1)))
fmt.Println(Same(tree.New(2), tree.New(2)))
}
package main
import (
"fmt"
"sync"
)
type FetchMap struct{
Mu sync.Mutex
Map map[string] int
}
var mymap = FetchMap{Map : make( map[string] int)}
type Fetcher interface {
// Fetch returns the body of URL and
// a slice of URLs found on that page.
Fetch(url string) (body string, urls []string, err error)
}
// Crawl uses fetcher to recursively crawl
// pages starting with url, to a maximum of depth.
func Crawl(url string, depth int, fetcher Fetcher) {
mymap.Mu.Lock()
_ , ok := mymap.Map[url]
mymap.Map[url] = 1
mymap.Mu.Unlock()
if ok {
return
}
// TODO: Fetch URLs in parallel.
// TODO: Don't fetch the same URL twice.
// This implementation doesn't do either:
if depth <= 0 {
return
}
body, urls, err := fetcher.Fetch(url)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("found: %s %q\n", url, body)
wg := sync.WaitGroup{}
wg.Add(len(urls))
for _, u := range urls {
go func (u string){
defer wg.Done()
Crawl(u, depth-1, fetcher)
}(u)
}
wg.Wait()
return
}
func main() {
Crawl("https://golang.org/", 4, fetcher)
}
// fakeFetcher is Fetcher that returns canned results.
type fakeFetcher map[string]*fakeResult
type fakeResult struct {
body string
urls []string
}
func (f fakeFetcher) Fetch(url string) (string, []string, error) {
if res, ok := f[url]; ok {
return res.body, res.urls, nil
}
return "", nil, fmt.Errorf("not found: %s", url)
}
// fetcher is a populated fakeFetcher.
var fetcher = fakeFetcher{
"https://golang.org/": &fakeResult{
"The Go Programming Language",
[]string{
"https://golang.org/pkg/",
"https://golang.org/cmd/",
},
},
"https://golang.org/pkg/": &fakeResult{
"Packages",
[]string{
"https://golang.org/",
"https://golang.org/cmd/",
"https://golang.org/pkg/fmt/",
"https://golang.org/pkg/os/",
},
},
"https://golang.org/pkg/fmt/": &fakeResult{
"Package fmt",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
"https://golang.org/pkg/os/": &fakeResult{
"Package os",
[]string{
"https://golang.org/",
"https://golang.org/pkg/",
},
},
}