推荐学习网站:菜鸟教程
注:golang不用打分号 !!!
另:当变量/类型/函数名等标识符以大写字符开头,则该标识符对外部可见(即Java中的public),否则对外不可见
头文件(包)的声明:imort
1 2 3 4 5 import "fmt" import ( "fmt" "..." )
基础框架
1 2 3 4 5 6 7 8 9 package mainimport ( "fmt" ) func main () { ... }
输入/输出
在go中,输入输出所在包为** fmt 基础包**
注:Print/Scan 首字母需要大写 !
输出
**%v 以默认格式打印值,打印任意类型的变量的值**
%+v:结构体时会显示字段名和值
%#v:值的Go语法表示
1 2 3 fmt.Print("There have " ,num," numbers" ) fmt.Println("Auto \0" ) fmt.Printf("%d + $d = %d" ,a,b,a+b)
输入
1 2 fmt.Scan(&a,&b) fmt.Scanf("%d %c" ,&a,&c)
常量
const同C,替代var
inta:在const内自动逐行计数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package mainimport "fmt" func main () { const ( a = iota b c d = "ha" e f = 100 g h = iota i ) fmt.Println(a,b,c,d,e,f,g,h,i) }
声明变量
注意:未使用过的变量会导致编译错误(全局变量除外)
在Go中,未初始化的变量会自动赋初始值(默认为”零值”)
int32 = int
int64 = long long
Go中有多种声明变量的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 var 变量名称 数据类型变量名称 := 值 eg: var a int = 1 ;a := [4 ]int {1 ,2 ,3 ,4 } a := 4 ; sum := a+b; var ( n int b bool num float32 )
函数
函数的声明:
1 2 3 func 数据名称(参数) (返回类型){ return 返回值 }
注意,同一函数返回多个值 是合法的:
1 2 3 func swap (x,y string ) (string string ){ return y,x }
构造函数与工厂函数 用于标准化构造结构体或其他自定义结构的函数
1 2 3 func NewPerson (name string , age int ) *Person { return &Person{Name: name, Age: age} }
函数一等公民
函数是一等公民是指函数在语言中具有与其他数据类型(如数字、字符串等)相同的地位
也就是说,函数可以被当做一种数据类型而被用作赋值、参数传递、返回值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 type mathOperation func (int , int ) int func add (a, b int ) int { return a + b } func calculate (op func (int , int ) int , a, b int ) int { return op(a, b) } func getMultiplier () mathOperation { return func (a, b int ) int { return a * b } } func main () { var operation mathOperation operation = add result := operation(3 , 4 ) fmt.Println("3 + 4 =" , result) result = calculate(add, 5 , 6 ) fmt.Println("5 + 6 =" , result) multiplier := getMultiplier() result = multiplier(3 , 7 ) fmt.Println("3 * 7 =" , result) }
for/gota/if/defer/switch
for
区别于C++,在Go中,for/if**不需要括号**框入三段式,且省略三段式时可省略分号:
1 2 3 4 5 6 7 8 9 for i := 1 ;i <= n;i++ { fmt.Print(i) ... } for sum <= n { sum++ ... }
另外,for循环的range形式可遍历切片或映射
当使用for循环遍历切片时,每次迭代都会返回两个值:第一个值为当前元素的下标,第二个值为改下表所对应的元素的一份副本
1 2 3 4 5 var num = []int {1 ,2 ,4 ,8 ,16 ,32 ,64 ,128 }for i, v := range num { fmt.Println("i=" ,i" v=" ,v) }
同时,可以将下标或值写为_以忽略它
for i, _ := range a
for _, value := range a
若只需要下标,忽略第二个变量即可
for i := range pow
gota
通过定义标签,跳转到被标记的区域 (尽在同一函数内有用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package mainimport "fmt" func main () { i := 0 Loop: fmt.Println(i) i++ if i < 5 { goto Loop } }
if
同时,if语句可以在条件表达式前**执行一个简短短语**(该语句声明的变量作用域仅在 if / else 之内):
1 2 3 4 if tmp := i*j;tmp <= max { tmp+=cnt ... }
defer
defer语句会将函数推迟到外层函数返回之后执行:
1 2 3 4 5 func main () { defer fmt.Print(" world!" ) fmt.Print("Hello" ) }
注:被推迟调用的函数会被压入一个栈中
switch
处理多分支情况
fallthrough可以在匹配一条 case 之后,继续执行后面的 case
1 2 3 4 5 6 7 8 t := time.Now() switch { case t.Hour() < 12 : fmt.Println("It's before noon" ) default : fmt.Println("It's after noon" ) }
指针
仅与C++不同的是,Go无法进行指针运算
注:Go语言对结构体指针提供了语法糖,即可以直接通过指针访问字段,而不用再显示解引用
1 2 3 4 5 (*target).Heath = 50 target.Health = 50
结构体
与C++仅声明格式不同:
1 2 3 4 5 6 type student struct { height int weight int score int name string }
字符
go中没有像c++中的char数据类型,与之相对的,go中有byte和rune两种数据类型
byte:用于存储ASCII中的字符
rune:用于存储任意Unicode字符
字符串
仅与C++不同的是,Go中字符串(直接声明的string)具有**不可变性**(内容不可修改)
另外,在"strings"包中,存在若干便携的字符串函数:
1 2 3 information := []string {"06072504" ,"2025212533" ,"Claran" } result1 := strings.Join(information,"-" ) ...
String & Stringf (fmt) 1 2 3 4 5 s1 := fmt.Sprint(x, y, z) fmt.Println(s1) s2 := fmt.Sprintf("x=%d, y=%.2f, z=%s" , x, y, z) fmt.Println(s2)
数组/切片
数组
数组声明格式:`var a [10]int` 10不能为变量,但是可以为 ... 代替不确定长度的数组长度
注意:Go语言中,数组的大小是类我,因此不同大小的数组是不兼容的。
Go的数组不能随意改变大小,因此Go有其独特的功能:**切片**
1 2 3 var a = [...]int {1 ,2 ,3 ,4 ,5 }b := [4 ]int {1 :2 ,3 :4 }
切片
类型 []T表示一个元素类型为T的切片,切片可以包含各种类型,包括其他切片。
切片通过两个下标来界定:上界与下界
a[low : high]
切片会选出一个区间,包含上界元素,但不包含下界元素
因此 a[1:4]实际包含了数组a[1]到a[3]的值
在进行切片时,可以忽略上下界。此时,被忽略的上下界分别默认为0和其底层数组长度n
另外,切片可以被声明为nil,即零值,此时其底层数组不存在,直到向其中添加值
1 2 3 4 var a []int base [101 ]int b ;= base[0 :51 ] c := base[:51 ]
此外,切片含3项结构:
指针(ptr)
**长度(len) **- 切片含数量
容量(cap) - 底层数组容量
切片的操作
make
格式:`make(数据类型,len,cap)`
make函数为Go内置函数,可以用来直接创建切片 –make函数会分配一个元素为零值的数组并返回一个引用了它的切片:
1 2 3 4 5 a := make ([]int , 5 ) b := make ([]int , 0 , 5 ) b = b[:cap (b)] b = b[1 :]
append
格式:`append(切片名称 , 添加元素1 , ... )`
append函数为Go的内置函数,可以用来为切片追加新的元素 。但被添加切片的底层数组太小,它就会被分配一个更大的数组。返回的切片会指向这个新分配的数组
1 2 3 4 5 var s []int s = append (s,0 ) s = append (s,1 ) s = append (s,2 ,3 ,4 )
len/cap
len()函数可以获取切片长度
cap()函数可以获取切片容量
copy
copy可用于拷贝切片
range
用于for循环中迭代数组、字符串、切片、channel或map
range在数组和切片中返回两个值:下标和对应值或只返回下标;在集合map中返回Key-value对
使用 _ 来忽略索引或值
例如:
1 2 3 4 a := [6 ]int {0 ,1 ,2 ,3 ,4 ,5 } for i, j := range a { fmt.Print(i," " ,j) }
map
与C++类似,map是一种无序的 索引-值 的集合
使用make或字面量来创建map
1 2 3 4 5 6 7 8 9 10 11 12 13 m := make (map [byte ]int ) m := map [byte ]int { 'A' = 65 , ... 'a' = 97 , ... } m['a' ] = 97 ... m['A' ] = 65 ... fmt.Print(m['f' ])
获取元素:
v, b := m[a] // 如果键不存在,则b的值为false,v2为零值
len、range同样对map适用
使用delete删除键值对:
delete(m,"a")
强制数制转换
> go不支持隐式类型转换
>
格式:float32(6)
strconv
使用 strconv.Atoi() 函数,可以自动解析字符串中的数字字符并返回相应整形
相反 strconv.Itoa() 函数,可以将整形转换为字符串
1 2 3 4 5 str := "123" var num int num, _ = strconv.Atoi(str) var s string s, _ = strconv.Itoa(num)
更多的strconv系列函数:
strconv.ParseFloat(str, 64) %s -> %f
strconv.FormatFloat(f, ‘f’, 2/精度 /, 64) %f -> %s