一、切片Slice
func main() {
fmt.Println("Hello, World!")
s := []int{1, 2, 3} //数组
printSlice(s)
fmt.Println(s[0:2]) //使用切片方式
fmt.Println(s[:2])
fmt.Println(s[0:])
fmt.Println(s[:])
s2 := make([]int, 3, 5) //通过make([]int, len, cap)来定义切片
printSlice(s2)
var s3 []int
if s3 == nil {
fmt.Println("s3切片为空")
}
printSlice(s3)
var s4 []int
s4 = append(s4, 0) //向s4空切片追加数据
printSlice(s4)
s4 = append(s4, 1) //向s4追加1个数据
printSlice(s4)
s4 = append(s4, 2,3,4) //向s4追加多个数据
printSlice(s4)
s5 := make([]int, len(s4), cap(s4) * 2) //创建s5切片,容量是其两倍
printSlice(s5)
copy(s5, s4) //将s4的内容拷贝到s5中
printSlice(s5)
s5 = append(s5, 6,7,8,9,10,11,12,13)//当添加的数据大于容量,会自动扩容
printSlice(s5)
//s5[13] = 14 //使用下标的情况,需要小于长度
s5 = append(s5, 14,15,16,17,18,19,20,21,22,23,24,25)
printSlice(s5)//可以看到cap容量扩容都是两倍扩容
}
func printSlice(x []int){
//切片不仅能使用len()来进行测量长度,还提供了cap()函数测量容量
fmt.Printf("len=%d cap=%d slice=%v
",len(x),cap(x),x)
}
二、范围Range
func main() {
fmt.Println("Hello, World!")
arr := []int{1, 2, 3}
for num := range arr { //如果定义一个变量来接收,是其下标值
fmt.Println(num)
}
for i, num := range arr { //i是下标,num是值,可以看出key,value两个返回值
fmt.Println(i, "", num)
}
for _, num := range arr { //如果不需要其中的某个返回值,直接用`_`来代替
fmt.Println(num)
}
m := map[string]string{"a": "apple", "b": "banana"}
for k, v := range m {//循环哈希表
fmt.Println(k,v)
}
s := "golang"
for i,c := range s{ //循环字符串,第一个参数是字符的索引,第二个是字符(Unicode的值)本身。
fmt.Println(i,c)
}
}
三、集合Map
var m map[string]string //声明map, map[key类型]value类型
m2 := make(map[string]string) //用make声明map
if m == nil { //空map
fmt.Println(m)
}
m2["abc"] = "ABC" //存入值
fmt.Println(m2["abc"]) //取出值
m2["啊"] = "啊啊啊"
for k, v := range m2 { //循环取值
fmt.Println(k, v, m2[k])
}
val, ok := m2["abc"] //两个返回值,第一个是值,第二个是状态
fmt.Println("val,ok:", val, ok)
fmt.Println(m2)
delete(m2, "abc")//删除 key为abc
fmt.Println(m2)
//链表
type LinkMap struct {
key string
value string
next *LinkMap
}
alink := LinkMap{"a","A",nil}
blink := LinkMap{"b","B",nil}
alink.next = &blink //只能存储其地址
fmt.Println(alink,alink.next)
//struct{}无是一个无元素的结构体类型,通常在没有信息存储时使用。优点是大小为0,不需要内存来存储struct {}类型的值。
//struct {} {}是一个复合字面量,它构造了一个struct {}类型的值,该值也是空。
var set map[string]struct{} //这个就形成set,因为struct{}{}是相等的
// Add some values to the set:
set["red"] = struct{}{}
set["blue"] = struct{}{}
// Check if a value is in the map:
_, ok := set["red"]
fmt.Println("Is red in the map?", ok) //结果是存在
_, ok = set["green"]
fmt.Println("Is green in the map?", ok)//结果不存在
四、递归
func Factorial(n uint32) (res uint32) {//来个阶乘n!,递归
if n > 0 {
return n * Factorial(n-1)
}
return 1
}
func main() {
res := Factorial(10)
fmt.Println(res)
}
func Fibonacci(n int) int {//斐波那契数列
if n < 2 {
return n
}
return Fibonacci(n-1) + Fibonacci(n-2)
}
func main() {
var i int
for i = 0; i < 10; i++ {
res := Fibonacci(i)
fmt.Println(res)
}
}
五、类型转换
func main() {
var a int32 = 10
var b int64 = 3
//b = a //不支持隐式转换,报错Cannot use 'a' (type int32) as type int64
//b = int64(a) //显式转换就可以了
var c float32
c = float32(a) / float32(b) //需要转换
var d = float32(a) / float32(b) //这个时候d可以不需要声明类型
var e = c + float32(b)
fmt.Println(c, d)
}
六、总结
切片(slice)、范围(range)、集合Map、递归函数基本上跟其他大部分语言都差不多。切片没有步长(类似python的array[::-1]就倒序),集合Map返回两个值,一个状态值。类型转换必须显式.