数组
package main
import "fmt"
// go语言 数组是值传递,这个函数只能传长度为 5 的int数组,传其他的会报错
func printArr(arr [5]int){
// 因为是值传递,函数内对修改元素不会影响原始数组
for i, v := range arr{
fmt.Println(i, v)
}
}
// 可以通过传指针来改变数组内的数据,但这里依然需要传指定长度的数组指针
func printArr2(arr *[5]int){
arr[0] = 100
fmt.Println(arr)
}
// 可以传切片,这样就不限长度了
func printArr3(arr []int){
for i, v := range arr{
fmt.Println(i, v)
}
}
func main() {
// 一维数组
var arr1 [5]int
arr2 := [5]int{1,2,3,4,5}
arr3 := [...]int{6,7,8,9,0,1,2,3}
fmt.Println(arr1, arr2, arr3)
// 二维
var grid [4][5]int
fmt.Println(grid)
// 遍历1
for i:= range arr3{
fmt.Println(i)
}
// 遍历2
for i, v := range arr3{
fmt.Println(i, v)
}
// 遍历3
for _, v := range arr3{
fmt.Println(v)
}
printArr(arr2)
printArr2(&arr2)
// 需要传切片
printArr3(arr2[:])
printArr3(arr3[:])
}
切片
package main
import "fmt"
// 传切片的函数
func test(arr []int){
arr[0] = 100
}
func main() {
arr := [...]int{1,2,3,4,5}
fmt.Println("可以用切片代替引用传递")
fmt.Println("\tarr:", arr)
test(arr[:])
fmt.Println("\ttest(arr[:]): 函数内修改数值生效", arr[:], "\n\n")
// 切片可以向后扩展
arr1 := [...]int{0,1,2,3,4,5,6,7}
fmt.Println("切片向后可以扩展, arr1:", arr1)
s1 := arr1[2:8] // {2, 3, 4, 5}
s2 := s1[3:5] // 本来应该只能取到 [3:4], 但是原数组中后面其实还有元素,这里并不会报错,而是会自动补齐 {5, 6}
s3 := s2[2:3] // 同理, 这里是 {6}
fmt.Println(s1, s2, s3)
// 添加元素
s4 := append(s1, 8) // s1 后没有了元素,即添加的位置 > cap, 此时会生成一个新的数组, 不再是视图 {}
s5 := append(s2, 9) // s2 后 还有个 7, 此处添加,会覆盖原数组的 7
fmt.Println(s4, s5)
// 建立切片的其他方式
var s []int
fmt.Println(s) // 只是一个空slice, 值为 nil
//方法二
s6 := []int{1,2,3,4}
fmt.Println(s6)
// 建一个指定长度的slice
s7 := make([]int, 10) // 初始值都为 0, len= 10, cap = 10
fmt.Println(s7)
// 可以指定大一点的cap, 方便扩展
s8 := make([]int, 10, 12) // len = 10, cap = 12
fmt.Println(s8)
// 拷贝 slice
copy(s8, s6) // 把 s6 拷贝进s8, 效果是,将s6 按顺序插入进 s8
fmt.Println(s8)
// 删除中间元素
//[1 2 3 4 0 0 0 0 0 0]
// 挺鸡肋的一种方式,操作起来很麻烦
s8 = append(s8[:3], s8[4:]...)
fmt.Println(s8)
// 删除头尾元素
s6 = []int{1,2,3,4,5}
s6 = s6[:len(s6)-1] // 删除尾
s6 = s6[1:] // 删除头
print("debug")
map
package main
import (
"fmt"
"sort"
)
func main() {
// 定义例子
m := map[string]string {
"name": "cccccc",
"shchool": "bbbb",
"home_address": "skjdkjk",
}
fmt.Println(m)
// 定义方法二
m2 := make(map[string]int) // 这样是定义一个空的map
fmt.Println(m2)
// 定义方法三
var m3 map[string]int
fmt.Println(m3)
// 遍历 map
for key, value := range m{
fmt.Println(key, value)
}
// 省略值
for key := range m{
fmt.Println(key)
}
// 省略 key
for _, value := range m{
fmt.Println(value)
}
// 获取值
name := m["name"]
fmt.Println(name)
// 获取不存在的key, 不会报错,而是返回空字符串
test := m["不存在"]
fmt.Println(test)
// 判断是否在 map 中
name2, exist := m["name"]
fmt.Println(name2, exist) // exist=true
test1, exist1 := m["不存在"]
fmt.Println(test1, exist1) // exist1=false
// 结合if
if _, ok := m["name"]; ok {
fmt.Println("存在")
}
// 删除元素
delete(m, "name")
fmt.Println(m)
// 添加
m["city"] = "北京"
fmt.Println(m)
// 结合 slice 按序遍历 map
var s []string
for key := range m{
s = append(s, key)
}
sort.Strings(s)
fmt.Println(s)
for _, v := range s{
fmt.Println(v, m[v])
}
}
字符和字符串处理
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
s := "hello你好啊" // 这个是utf-8编码,字符所占字节是可变化的,英文1字节, 中文3字节
// 计算这个字符串长度,len(s) = 5 + 3 * 3 = 14, 这里实际上计算的是 字节长度
fmt.Println(len(s))
// 可以用按字节打印出来
for _, b := range []byte(s){
fmt.Printf("%X ", b)
}// 68 65 6C 6C 6F E4 BD A0 E5 A5 BD E5 95 8A, 中文是3个字节
// 标准的 unicode, 即 UCS-2, 每个字符是占用2个字节,即无论英文还是中文,都是2个字节
fmt.Println("")
// 按照 字符 打印出来
for i, ch := range s{
fmt.Printf("(%d, %X) ", i, ch)
} // (0, 68) (1, 65) (2, 6C) (3, 6C) (4, 6F) (5, 4F60) (8, 597D) (11, 554A)
// 打印出来是 8个字符, 中文如 “你” 的字符编码是 4F60, 2个字节
// 通过debug 可以知道 ch 的数据类型是 int32, int32有个别名,也叫 rune, 是4字节
// 所以 编译器是将原本 "你" (utf-8编码),解码成3个字节(E4BDA0),转换成了 2个字节的unicode编码(4F60),
// 然后将这连个字节放到 4个字节的数据类型-rune 中
fmt.Println("")
// 使用utf8.RuneCountInString() 可以计算utf8字符串中 的 rune 字符个数
fmt.Println(utf8.RuneCountInString(s)) // 8
// 可以正常计算字符数量
// 总结:将utf8字符串 按 “英文1个字节,中文3个字节” 解码成字节流,
//然后再编码成 unicode,英文还是1字节,中文3字节变2字节,之后把1字节的英文和2字节的中文,都放入 4字节的 rune 中
bytes := []byte(s)
for len(bytes) > 0{
ch, size := utf8.DecodeRune(bytes) // 取出"第一个"字符的字符编号和所占字节(英文1个,中文3个)
fmt.Printf("%c", ch)
bytes = bytes[size:]
}
fmt.Println("")
// 可以直接转成 rune 数组
for i, ch := range []rune(s){
fmt.Printf("(%d, %c)", i, ch)
}
}