golang 学习笔记

array

  • 数组初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 一维数组
var a [4]int //元素自动初始化为零[0 0 0 0]
b := [4]int{2, 5} //未提供初始化值得元素自动初始化为0 [2 5 0 0]
c := [...]int{1, 2, 3} //编译器按初始化值数量确定数组长度 [1 2 3]
d := [2]string{"TigerwolfC", "chen_peggy"}
e := [...]int{10, 3: 100} //支持索引初始化,但注意数组长度与此有关 [10 0 0 100]
f := [4]string{1: "b", 3: "c"} // 可以指定初始化的位置

# 复合类型数组
type User struct {
Name string
Age byte
}
d := [...]user{
{"TigerwolfC", 20}, // 可省略元素类型。
{"chen_peggy", 18}, // 别忘了最后一行的逗号。
}
  • 数组去重
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package main

import (
"fmt"
"sort"
)

func RemoveDuplicate(v []int) []int {
//为了性能需要尽可能的减小拷贝,最悲观的情况每个元素只移动一次。
toIndex := 0
p := 0

for i := range v {
// 为了实际去重结构时减小内存拷贝
c := &v[i]

if p == *c && i != 0 {
// 重复内容,跳过
continue
}

if i != toIndex {
// 需要移动当前元素
v[toIndex] = *c
}

toIndex++
p = *c
}

return v[:toIndex]
}

func main() {
v := []int{9, 1, 1, 9, 2, 2, 3, 3, 3, 4, 5, 6, 7, 7, 7, 7, 8}

// 升序排序
sort.Slice(v, func(i, j int) bool { return v[i] <= v[j] })
//sort.Ints(v)

// 去重
v = RemoveDuplicate(v)

// 打印结果
// []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Printf("%#v", v)
}


// 字符类型数组去重

func ArrayRemoveRepeated(arr []string) []string {
sort.Strings(arr)
i := 0
var j int
for {
if i >= len(arr)-1 {
break
}
for j = i + 1; j < len(arr) && arr[i] == arr[j]; j++ {
}
arr = append(arr[:i+1], arr[j:]...)
i++
}
return arr
}
  • 删除数组中的某个元素
1
2
// 删除第 i 个元素
a = append(a[:i], a[i+1:]...)

string

  • 字符串分割
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
str := "-100 123 200"

//指定分割符
countSplit := strings.Split(str, " ")
fmt.Println(countSplit, len(countSplit))

//指定分割符,指定分割次数
countSplit = strings.SplitN(str, " ", 2)
fmt.Println(countSplit, len(countSplit))
}

["-100" "123" "200"] 3
["-100" "123 200"] 2
  • 删除某个字符
1
2
# 删除下标为 i 的字符
str = str[:i] + str[i+1:]

注: 遍历字符串时删除字符可能会导致错位。

  • 字符判断

    • 判断是否为字母:unicode.IsLetter(v)
    • 判断是否为十进制数字:unicode.IsDigit(v)
    • 判断是否为数字:unicode.IsNumber(v)
    • 判断是否为空白符号:unicode.IsSpace(v)
    • 判断是否为 Unicode 标点字符:unicode.IsPunct(v)
  • 字符串查找

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
40
41
42
43
44
45
// 查找某个字符是否在这个字符串中存在
fmt.Println(strings.Contains("widuu", "wi")) //true
fmt.Println(strings.Contains("wi", "widuu")) //false

// 查询字符串中是否包含多个字符
fmt.Println(strings.ContainsAny("widuu", "w&d")) //true

// 查询字符串中是否包含rune类型
// rune类型是utf8.RUneCountString可以完整表示全部Unicode字符的类型
fmt.Println(strings.ContainsRune("widuu", rune('w'))) //true
fmt.Println(strings.ContainsRune("widuu", 20)) //fasle

// 输出,在一段字符串中有多少匹配到的字符
fmt.Println(strings.Count("widuu", "uu")) //1
fmt.Println(strings.Count("widuu", "u")) //2

// 查找字符串,然后返回当前的位置,输入的都是string类型,然后返回的int是位置信息
fmt.Println(strings.Index("widuu", "i")) //1
fmt.Println(strings.Index("widuu", "u")) //3

// 查找,字符串第一次出现的位置,如果不存在就返回-1
fmt.Println(strings.IndexAny("widuu", "u")) //3

// 查找第一次粗线的位置,只不过这次C是byte类型的,查找到返回位置,找不到返回-1
fmt.Println(strings.IndexByte("hello xiaowei", 'x')) //6

// 查找位置,只不过这次是rune类型的
fmt.Println(strings.IndexRune("widuu", rune('w'))) //0

// 通过类型的转换来用函数查找位置
func main() {
fmt.Println(strings.IndexFunc("nihaoma", split)) //3
}
func split(r rune) bool {
if r == 'a' {
return true
}
return false
}

// 查找的是最后出现的位置,正好跟index相反
fmt.Println(strings.LastIndex("widuu", "u")) // 4

// 跟indexAny正好相反,也是查找最后一个
fmt.Println(strings.LastIndexAny("widuu", "u")) // 4

go_tips

  • 格式化 int,位数不够,用 0 补齐
1
2
n := 32
sInt := fmt.Sprintf("%07d", n) // 0000032
  • %v 按默认格式输出,

  • %+v 在%v的基础上额外输出字段名,

  • %#v 在%+v的基础上额外输出类型名。

  • 用两个协程,依次打印121212

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
func main() {
done := make(chan bool) //控制结束退出的信号
order1 := make(chan bool, 1)
order2 := make(chan bool, 1)
order1 <- true
go func() {
for {
<-order1
fmt.Println(1)
order2 <- true
}
}()

go func() {
for {
<-order2
fmt.Println(2)
order1 <- true
}
}()
go func() {
time.Sleep(1 * time.Second)
done <- true
}()
//阻塞等待退出信号
<-done
}

  • 随机数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main //必须有个main包

import "fmt"
import "math/rand"
import "time"

func main() {
//设置种子,只需一次
//rand.Seed(123) 如果种子参数一样,每次运行程序产生的随机数都一样
rand.Seed(time.Now().UnixNano()) //以当前系统时间作为种子参数

for i := 0; i < 5; i++ {
//产生随机数
//fmt.Println("rand = ", rand.Int()) //随机很大的数
fmt.Println("rand = ", rand.Intn(100)) //限制在100内的数
}

}

  • Golang 接口功能演示
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
40
41
42
43
44
45
46
47
package main

import (
"fmt"
"math"
)

type geometry interface {
area() float32
perimeter() float32
}

type rect struct {
width, height float32
}
type circle struct {
radius float32
}

func (r rect) area() float32 {
return r.height * r.width
}

func (c circle) area() float32 {
return math.Pi * c.radius * c.radius
}

func (r rect) perimeter() float32 {
return 2 * (r.height + r.width)
}

func (c circle) perimeter() float32 {
return 2 * math.Pi * c.radius
}

func measure(g geometry) {
fmt.Println("面积:", g.area())
fmt.Println("周长:", g.perimeter())
}

func main() {
r := rect{3, 4}
measure(r)
c := circle{3}
measure(c)
}

运行结果:

1
2
3
4
面积: 12
周长: 14
面积: 28.274334
周长: 18.849556

  • 将ip范围转换成ip掩码

from: ip2cidr

1
2
3
cidrs, err := ip2cidr.IPRangeToCIDR("10.0.16.2", "10.0.8.9")
fmt.Println(err)
fmt.Println(cidrs)

运行结果:

1
2
<nil>
[10.0.6.2/31 10.0.6.4/30 10.0.6.8/29 10.0.6.16/28 10.0.6.32/27 10.0.6.64/26 10.0.6.128/25 10.0.7.0/24 10.0.8.0/29]