funcadd(x int, y int)int{return x + y
}// 也可以写成这样 func add(x, y int) int{}// 函数可以返回任意数量的返回值funcswap(x, y string)(string,string){return y, x
}
变量声明
var flag1, flag boolvar i int// 声明的时候进行初始化var i, str int,string=1,"abc"// 如果初始化值存在,那么可以省略类型,系统可以自动从初始值中获得类型,比如:var i, str =1,"abc"// 在函数内可以用:=代替var进行声明
i, str :=1,"abc"
常量声明
const world ="世界"
类型转换
// 需要显式转换var i int=42var f float64=float64(i)var u uint=uint(f)
流程控制语句
for语句
for i:=0; i<10; i++{
fmt.Println(i)}
while语句
sum :=0for i<10{
sum += i
}
if语句
if i <10{
fmt.Println(i)}// 同 for 一样, if 语句可以在条件表达式前执行一个简单的语句。该语句声明的变量作用域仅在 if 之内。// 在 if 的简短语句中声明的变量同样可以在任何对应的 else 块中使用。funcjudge(a, b, c float64)float64{ifvar:= math.Pow(a, b);var< c {return c
}}
switch语句
// 每条case语句自带break// switch语句也可以不带条件,就等同于if-else语句funcmain(){
fmt.Print("Go runs on ")switch os := runtime.GOOS; os {case"darwin":
fmt.Println("OS X.")case"linux":
fmt.Println("Linux.")default:
fmt.Printf("%s.\n", os)}}
defer语句
funcmain(){defer fmt.Println("world")
fmt.Println("hello")}// 被defer的语句会被压入一个栈中,之后执行按照出栈顺序执行funcmain(){
fmt.Println("counting")for i :=0; i <10; i++{defer fmt.Println(i)}
fmt.Println("down")}/* 执行结果
counting
down
9 8 7 6 5 4 3 2 1 0
*/
struct slice和映射
指针
funcmain(){
i, j :=42,2701
p :=&i // 指向 i
fmt.Println(*p)// 通过指针读取 i 的值*p =21// 通过指针设置 i 的值
fmt.Println(i)// 查看 i 的值 i的值为21
p =&j // 指向 j*p =*p /37// 通过指针对 j 进行除法运算
fmt.Println(j)// 查看 j 的值}
结构体
type Vertex struct{
X int
Y int}funcmain(){
v := Vertex{1,2}
v.X =4
v1 := Vertex{X:1}// Y缺省
fmt.Println(v.X)}// 结构体指针funcmain(){
v := Vertex{1,2}
p :=&v
p.X =1e9// 这里可以省略(*p).X
fmt.Println(v)}
数组
funcmain(){// 声明方式1var a [2]string
a[0]="Hello"
a[1]="World"// 声明方式2
primes :=[6]int{2,3,5,7,11,13}}
切片
funcmain(){
primes :=[6]int{2,3,5,7,11,13}// 或者写成这样 primes := []int{2, 3, 5, 7, 11, 13}// 声明方式1var s []int= primes[1:4]// 声明方式2
p := primes[1:4]
fmt.Println(s)}// 更改切片的元素会修改其底层数组中对应的元素。// var a [10]int 则a[0:10] a[:10] a[0:] a[:]是等价的// 切片有长度和容量,长度指的是切片中元素的个数,容量是指从切片中第一个元素到底层数组最后一个元素的个数
s :=[]int{2,3,5,7,11,13}
s = s[:0]// len(s)=0 cap(s)=6 s=[]
s = s[:4]// len(s)=4 cap(s)=6 s=[2357]
s1 = s[2:]// len(s)=2 cap(s)=4 s1=[57]
s2 = s[2:6]// len(s)=4 cap(s)=4 s2=[571113] 从切片s的第三个元素开始数4个// 切片的零值是 nil。nil 切片的长度和容量为 0 且没有底层数组。// 用make创建动态数组
a :=make([]int,5)// len(a) = cap(a) = 5
b :=make([]int,0,5)// len(b)=0 cap(b)=5// 二维切片
board :=[][]string{[]string{"_","_","_"},[]string{"_","_","_"},[]string{"_","_","_"},}
board[0][0]="x"// 用append给切片添加元素,如果添加之后元素的个数大于底层数组的容量,会自动增加底层数组的容量var a []int
a.append(a,1)
a.append(a,2,3,4)// range遍历切片,返回的第一个值是数组下标,第二个是元素var pow =[]int{1,2,4,8,16,32,64,128}funcmain(){for i, v :=range pow {
fmt.Printf("2**%d = %d\n", i, v)}}// 如果只想要索引for i :=range pow
// 如果只想要值for_, v :=range pow
映射
type Vertex struct{
Lat, Long float64}var m =map[string]Vertex{"Bell Labs": Vertex{40.68433,-74.39967},"Google": Vertex{37.42202,-122.08408},}// 推荐以下方式
m :=make(map[string]int)
m["anny"]=1
m["belta"]=2// 删除delete(m,"anny")
v, ok := m["anny"]// 返回的是0, false
v, ok := m["belta"]// 返回的是2, true
函数闭包
// 一个函数返回另一个函数 另一个函数和函数体外的某个变量联系在一起 相当于递归funcadder()func(int)int{
sum :=0returnfunc(x int)int{
sum += x
return sum
}}funcmain(){
pos, neg :=adder(),adder()for i :=0; i <10; i++{
fmt.Println(pos(i))}}// 实现斐波那契// 实际上就是把递归中循环用到的值通过函数体外变量的方式记录下来funcfibonacci()func()int{
pre1 :=0
pre2 :=1returnfunc()int{
temp := pre1
pre1 = pre2
pre2 = temp + pre2
return temp
}}funcmain(){
f :=fibonacci()for i :=0; i <10; i++{
fmt.Println(f())}}
方法和接口
为结构体定义方法
type Vertex struct{
X, Y float64}// 调用方法时为v.Abs()func(v Vertex)Abs()float64{return math.Sqrt(v.X*v.X + v.Y*v.Y)}
指针接受者和值接受值
// 值接受者 调用函数之后不会改变v的值func(v Vertex)Abs()float64{return math.Sqrt(v.X*v.X + v.Y*v.Y)}// 指针接受者 调用函数之后会改变v的值/*
该方法被调用时 接受者既可以为值也可以为指针
var v Vertex
v.Scale(5) // OK
p := &v
p.Scale(10) // OK
*/func(v *Vertex)Scale(f float64){
v.X = v.X * f
v.Y = v.Y * f
}// 改写的函数/*
该方法被调用时 接受者只能为指针
var v Vertex
ScaleFunc(v, 5) // 编译错误!
ScaleFunc(&v, 5) // OK
*/funcScaleFunc(v *Vertex, f float64){
v.X = v.X * f
v.Y = v.Y * f
}
接口
type Animal interface{eat()}type Cat struct{
name string}func(cat Cat)eat(){
fmt.Println("fish")}type Dog struct{
name string}func(dog Dog)eat(){
fmt.Println("meat")}funcmain(){var I Animal =Cat("miao")
I.eat()}// 空接口 用来处理未知类型的值 var i interface{}// 下面是一个例子funcdo(i interface{}){switch v := i.(type){caseint:
fmt.Printf("Twice %v is %v\n", v, v*2)casestring:
fmt.Printf("%q is %v bytes long\n", v,len(v))default:
fmt.Printf("I don't know about type %T!\n", v)}}funcmain(){do(21)do("hello")do(true)}