Go语言是Google的大牛们发明的一门新语言,2012年3月28日正式对外发布。去年7月份我第一次接触到Go语言,从此就喜欢上了它。本来这门语言是为C/C++程序员准备的,但是貌似更多的是Python程序员在学习和使用。
Go语言的主要特性有:
- 自动垃圾回收
- 丰富的内置语言类型
- 函数多返回值
- 错误处理
- 匿名函数和闭包
- 类型和接口
- 并发编程
- 反射
- 语言交互性
Hello world
hello.go
package main import "fmt" //需要使用fmt包中的Println()函数 func main(){ fmt.Println("Hello world") }
运行
有两种方式运行
//解释执行 >go run hello.go //编译执行 go build hello.go hello.exe
代码解读
1.每个Go的源代码开头都是一个package的声明,表示该Go代码所属的包。要生成Go可执行程序,必须建立一个名字为main的包,并且在该包中包含一个main()的函数,该函数不带参数,也没有返回值。
2. import用来导入程序中需要的包,如果导入的包没有被使用,Go的编译器会报错,支持相对路径和绝对路径。
3.Go的函数结构为:
func 函数名(参数列表)(返回值){
//函数结构体
}
如:
func T(value1 int, value2 string)(result int, er error){
//....
}
函数以func开头,参数类型在参数的后面,如果有返回值在参数后面列出,强制左花括号必须在函数定义的第一行。
4.注释支持
/* 块注释 */ //行注释
变量
Go语言的变量声明和C/C++有明显的区别,它引入了关键字var,而且类型信息是放在变量名后面的。
变量的声明 var v1 int var v2 string var v3 [10] int //数组 var v4 [] int //数组切片 var v5 struct{ f int } var v6 int //指针 var v7 map[string]int var v8 func(a int)int 变量的初始化 var v1 int = 10 var v2 = 10 //编译器可以自动推导出v2的类型 var := 10 //编译器可以自动推到处v3的类型 := 不需要var来声明,一步到位,如果已经被声明,就不能使用这个符号了,否则会报错(no new variables on left side of :=) 变量赋值 var v10 int声明后,可以赋值 v10 = 10 多重赋值 i,j = j,i //无需加入中间变量 匿名变量 有的时候,我们需要获取函数返回的某一个值,却因为该函数返回多个值而定义许多没用的变量,从而导致不够优雅,Go有效的解决了这个问题,对于不用的变量,可以使用_来代替。 例如: func getName()(furstname,lastname,nickname){ return "David","Yang","D" } 如果只想获得第一个变量,可以这样来写代码 name,_,_ := getName()
常量
常量是指编译期间就已知并且不可改变的值,可以是数值类型(包括整型,浮点型,复数类型),布尔类型,字符串类型等。
const Pi = float64 = 3.14159275358979 const zero = 0.0 const ( size int64 = 1024 eof = -1 ) const a,b,c = 3,4,"foo" 常量赋值必须保证右边的值在编译期间运算的常量表达式,如果在运行期间才知道返回结果,在编译器内并不能保证,就会导致编译错误。 预定义常量 预定义了true,false和iota iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在洗衣歌const出现之前,没出现一次,其代表的数字就会自动增1. const( c1 = iota //c1==0 c2 = iota //c2==1 c3 = iota //c3==2 ) const x = iota //x==0 const y = iota //y==0
类型
Go语言内置了一下类型
- 布尔bool (不能接受其他类型的赋值,不支持自动或者强制的类型转换)
- 整形int8,byte,int16,int,uint,uintptr等(int和int32会认为是不同的类型,不能直接比较,编译器不会做强转)
- 浮点float32,float64(float32相当于C语言的float,float64相当于double)
- 复数complex64,complex128 (value = 3.2 + 12i)
- 字符串string (Go 语言仅支持UTF-8和Unicode)
- 字符rune
- 错误error
此外,还有一些复合类型
- 指针
- 数组
- 切片
- 字典
- 通道
- 结构体
- 接口
字符串遍历
以字节数组的方式遍历 package main import ( "fmt" ) func main(){ str := "hello,世界" //每个汉字在UTF-8中占3个字节 n := len(str) for i := 0; i < n; i++ { ch := str[i] fmt.Println(i, ch) } } 输出: 0 104 1 101 2 108 3 108 4 111 5 44 6 228 7 184 8 150 9 231 10 149 11 140 以Unicode字符遍历 package main import ( "fmt" ) func main(){ str := "hello,世界" for i,ch := range str { //ch的类型为rune fmt.Println(i,ch) } } 0 104 1 101 2 108 3 108 4 111 5 44 6 19990 9 30028 以unicode字符方式遍历时,每个字符的类型是rune(早期的Go语言使用int类型表示Unicode字符),而不是byte.Go语言中支持两个字符类型,一个是byte(是unit8的别名),代表UTF-8字符串的单个字节的值;另一个是rune,代表单个Unicode的字符。出于简化语言的考虑,Go语言的多数API都假设字符串为UTF-8。
func main() { var a [5]int fmt.Println("array a:", a) a[1] = 10 a[3] = 30 fmt.Println("assign:", a) fmt.Println("len:", len(a)) b := [5]int{1, 2, 3, 4, 5} fmt.Println("init:", b) var c [2][3]int for i := 0; i < 2; i++ { for j := 0; j < 3; j++ { c[i][j] = i + j } } fmt.Println("2d: ", c) } Go语言中数组是一个值类型,所有的值类型变量在赋值和作为参数传递时都将产生一次复制动作,如果将数组作为函数的参数来调用时,该参数将发生数据复制,因此无法修改传入的数组内容,因为函数内操作的只是所传入数组的一个副本。
使用数组创建 a := [5]int{1, 2, 3, 4, 5} b := a[2:4] // a[2] 和 a[3],但不包括a[4] b = a[:4] // 从 a[0]到a[4],但不包括a[4] b = a[2:] // 从 a[2]到a[4],且包括a[2] 直接创建 slice1 := make([]int,5)//创建一个初始个数为5的切片,初始值为0 slice2 := make([]int,5,10)//预留10个元素的存储空间 len()和cap()可以得到元素个数和数组切片分配的空间大小 遍历 for i,v := range slice2 { fmt.Println("slice2[",i,"] =",v)//range表达式有两个返回值,索引和值 }
package main import "fmt" func main(){ m := make(map[string]int) //使用make创建一个空的map m["one"] = 1 m["two"] = 2 m["three"] = 3 fmt.Println(m) //输出 map[three:3 two:2 one:1] (顺序在运行时可能不一样) fmt.Println(len(m)) //输出 3 v,ok := m["two"] if ok { fmt.Println(v) } delete(m, "two") fmt.Println(m) //输出 map[three:3 one:1] m1 := map[string]int{"one": 1, "two": 2, "three": 3} fmt.Println(m1) //输出 map[two:2 three:3 one:1] (顺序在运行时可能不一样) for key, val := range m1{ fmt.Printf("%s => %d \n", key, val) /*输出:(顺序在运行时可能不一样) three => 3 one => 1 two => 2*/ } }
- 条件: if else和else if
- 选择: switch,case和select
- 循环: for和range
- 跳转:goto
条件 if a<10 { return 0 }else{ return 1 } 1.条件无括号 2.左花括号必须与if和else出于同一行 选择 swicth i { case 0: fmt.Println("0") case 1: fmt.Println("1") case 2: fmt.Println("2") default: fmt.Println("default") } 1.左花括号必须与swicth出于同一行 2.无需break 循环 sum :=0 for i := 0; i < 10; i++ { sum += i } sum := 0 for { sum ++ if sum >100 { break } } 跳转 fun fun1(){ i := 0 HERE: fmt.Println(i) i++ if < 10 { goto HERE } }