0%

Go语言收集

所谓的成功,就是用自己的方式度过人生。

学习资料

  1. The Go Programming Language
  2. Go语言中文网
  3. 菜鸟教程
  4. GitHub-Chinese-Top-Charts
  5. Go’s Declaration Syntax
  6. 雪花算法
  7. Go核心
  8. Go语言之旅
  9. 剑指Offer-Golang实现
  10. Golang面试题搜集
  11. go-interview
  12. 超全golang面试题合集
  13. 为什么Golang中不用this和self
  14. 新手可能会踩的50个坑

Nginx反向代理Go

一、安装nginx

二、安装go

三、代码

  1. cd ~/go/src && mkdir web
  2. vim test.go
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
67
68
69
70
71
package main

import (
"fmt"
"log"
"net/http"
"strings"
)

func printRequest(r *http.Request) {
fmt.Println("r.Form=", r.Form)
fmt.Println("r.PostForm=", r.PostForm)
fmt.Println("path=", r.URL.Path)
fmt.Println("scheme=", r.URL.Scheme)
fmt.Println("method=", r.Method)

fmt.Println("Get参数列表")
for k, v := range r.Form {
fmt.Println("Http Get["+k+"]=", strings.Join(v, " ; "))
}

fmt.Println("Post参数列表")
for k, v := range r.PostForm {
fmt.Println("Http Post["+k+"]=", strings.Join(v, " ; "))
}

fmt.Println("表单参数列表")
arraA := r.Form["a"]
fmt.Println("r.Form['a']=", arraA)
if len(arraA) > 0 {
fmt.Println("r.Form['a'][0]=", arraA[0])
}
}

func defaultFunc(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析参数
fmt.Println("This is func default")
printRequest(r)

fmt.Fprintf(w, "This is a default method")
}

func testFunc(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析参数
fmt.Println("This is func test")
printRequest(r)

fmt.Fprintf(w, "Func Test")
}

func anotherFunc(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //解析参数
fmt.Println("This is func another")
printRequest(r)

fmt.Fprintf(w, "Another Func")
}

func main() {
http.HandleFunc("/", defaultFunc)
http.HandleFunc("/test", testFunc)
http.HandleFunc("/another", anotherFunc)

err := http.ListenAndServe(":9090", nil)

if err != nil {
log.Fatal("Error:", err)
}

}

  1. 运行go run test.go,浏览器打开localhost:9090,可看到终端输出
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
This is func another
r.Form= map[a:[b] id:[1]]
r.PostForm= map[]
path= /another
scheme=
method= GET

Get参数列表
Http Get[id]= 1
Http Get[a]= b

Post参数列表

表单参数列表
r.Form['a']= [b]
r.Form['a'][0]= b
This is func default
r.Form= map[]
r.PostForm= map[]
path= /favicon.ico
scheme=
method= GET

Get参数列表

Post参数列表

表单参数列表
r.Form['a']= []

四、设置反向代理

  1. 进入nginx配置目录cd /path/nginx/conf/vhost
  2. vim go.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 8081;
#server_name go.cn;

access_log logs/go.access.log;
error_log logs/go.error.log;
root html;
index index.html index.htm index.php;

location / {
proxy_pass http://localhost:9090;#go 服务器可以指定到其他的机器上,这里设定本机服务器

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
  1. 运行go run index.go,浏览器打开localhost:8081,可看到对应输出

Go语言文件读取的几种方式

一、基础

读取文件有三种方式:将文件整个读入内存、按行读取、按字节数读取。

  1. 将文件整个读入内存

  2. 按行读取

  3. 按字节读取

二、参考

  1. 参考一
  2. 参考三

Go语言实现OOP

一、基础

      Golang是支持面向对象编程特性的语言,不过在Golang中没有类的概念,而是一些别的方式来实现。

  1. struct:通过给结构体类型定义方法实现传统OOP中的方法,具体做法是在方法当中定义接收者(类型接收者或指针接收者),位于func关键字和方法名之间。

    • 当接收者是指针类型时,调用时和类型接收者一样,Golang内部会自动转化
    • 结构体是值类型
    • 结构体的所有字段在内存中是连续的
    • 结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的属性(名字、个数、类型)
    • 结构体进行type重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转
    • 结构体的每个字段上可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和反序列化
  2. interface

    • interface是方法的集合,要实现一个接口,必须实现该接口里面的所有方法
    • 如果一个interface没有任何方法,则称该接口为空接口,任何类型都实现了空接口,空接口可以作为任何类型数据的容器
    • interface是Golang中实现多态的一种形式
    • interface可以嵌套,可以简单理解为继承
      • 子接口拥有父接口的所有方法,想要使用该子接口的话,则必须将父接口和子接口的所有方法都实现
    • interface也可以进行类型转换
    • interface只有方法声明,没有实现,没有数据字段
  3. map

  4. reflection

二、实现

  1. 封装

  2. 继承

  3. 多态

三、参考

  1. 参考一
  2. 参考二
  3. 参考三
  4. 参考四

指针操作:取地址&和取值*

一、基础

  1. 变量名前面添加&操作符(前缀)来获取变量的内存地址,即取地址操作
  2. 对指针使用*操作符,即指针取值操作

二、demo

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
package main

import (
"fmt"
)


func main() {
var a int = 3
var b int = 3
var c int = a * b
fmt.Println(c)

var house = "liusir.me"
ptr := &house
fmt.Printf("house address: %p\n", ptr)
fmt.Printf("ptr address: %p\n", &ptr)
fmt.Printf("ptr type: %T\n", ptr)
fmt.Printf("ptr value: %s\n", *ptr)
*ptr = "liuyulong"
fmt.Printf("ptr new value: %s\n", *ptr)

fmt.Println("====")

value := &ptr
fmt.Printf("value type: %T\n", value)
fmt.Printf("value: %s\n", **value)
}

三、参考

  1. 参考一

括号匹配

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
package main

import "fmt"

type Stack struct {
top int
data []interface{}
}

func (s *Stack) InitList(maxSize int) {
s.data = make([]interface{}, maxSize)
s.top = -1
}

func (s Stack) isNull() bool {
return s.top == -1
}

func (s Stack) isFull() bool {
return s.top >= cap(s.data)-1
}

func (s *Stack) Push(Element interface{}) bool {
if s.isFull() {
return false
}
s.top++
s.data[s.top] = Element
return true
}

func (s *Stack) Pop() (interface{}, bool) {
if s.isNull() {
return nil, false
}
e := s.data[s.top]
s.top--
return e, true
}

func MatchBracket(str string) bool {
s := Stack{}
// s.InitList(30)
s.InitList(len(str))
for i := 0; i < len(str); i++ {
if str[i] == '(' && !s.isFull() {
s.Push(str[i])
}
if str[i] == ')' {
if s.isNull(){
return false
}
s.Pop()
}
}

return s.top == -1
}

func main() {
fmt.Println(MatchBracket("(((((((((((((((((((((((((((((())))))))))))))))))))))))))))))"))
fmt.Println(MatchBracket("(((("))
}

go-redis

一、基础

二、代码

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package main

import (
"context"
"fmt"
"math/rand"
"time"

"github.com/go-redis/redis"
)

const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

var redisdb *redis.Client
var ctx = context.Background()

func randStr(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}

func randomInt(start int,end int) int{
rand.Seed(time.Now().UnixNano())
random:=rand.Intn(end-start)
random = start + random
return random
}


func initRedis()(err error){
redisdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
pong, err := redisdb.Ping(ctx).Result()
fmt.Println(pong, err)

key := "testZset"
for i:=0;i<=1000000;i++ {
member := randStr(16)
score := randomInt(0, 10000)
items := []redis.Z{
redis.Z{Score: float64(score),Member:member},
}
// fmt.Println(items)
_,err1 := redisdb.ZAdd(ctx, key, items...).Result()
if err1 != nil {
fmt.Printf("redis zadd failed! err:%v\n",err1)
return
}
}
return
}

func insertData() {
key := "testZset"
member := randStr(16)
score := randomInt(0, 10000)
items := []redis.Z{
redis.Z{Score: float64(score),Member:member},
}
fmt.Println(items)
_,err1 := redisdb.ZAdd(ctx, key, items...).Result()
if err1 != nil {
fmt.Printf("redis zadd failed! err:%v\n",err1)
return
}
}


func main() {
err := initRedis()
if err != nil {
fmt.Printf("connect redis failed! err : %v\n",err)
return
}
// error
// insertData()
}

字符串全排列

一、代码

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main

import (
"fmt"
"sort"
)

func permutation1(s string) []string {
var (
//tags保存字符串各个字符是否被使用过的标志,注意key值是s中字符的下标,不是字符,因为s可能是abbc这种
tags = make(map[int]bool, 0)
//res保存需要返回的结果
res = make([]string, 0)
//str将s类型转换,排序用
str = []byte(s)
)
//需要先将s排序,将abcb排序为abbc这种
sort.Slice(str, func(i, j int) bool { return str[i] < str[j] })
s = string(str)
//递归调用
dfs(s, tags, 0, "", &res)

return res
}

func dfs(s string, tags map[int]bool, index int, resStr string, res *[]string) {
//递归终止条件
if index >= len(s) {
*res = append(*res, resStr)
return
}
//遍历处理字符串
for i := 0; i < len(s); i++ {
//如果s[i]没被使用过,将其与resStr连接,标志位标记为已使用,然后进入
//注意tags的key值为下标值不是字符串,递归返回后一定要将刚刚处理的字符状态归为
if tags[i] == false {
resStr += string(s[i])
tags[i] = true
dfs(s, tags, index+1, resStr, res)
resStr = resStr[:len(resStr)-1]
tags[i] = false

//处理重复的情况,如果有重复的,只递归处理一次,避免重复
for {
if i < len(s)-1 && s[i] == s[i+1] {
i++
} else {
break
}
}
}
}
}

func permutation2(str string) []string {
var result []string
if str == "" {
return result
}
fmt.Println(str)
str1 := []byte(str)
fmt.Println(str1)

permutationHandler([]byte(str), 0, &result)
return result
}

func permutationHandler(strByte []byte, i int, result *[]string) {
length := len(strByte)
if i != length {
//利用map排除重复字符
strMap := make(map[string]int)
//固定首字符,递归剩余字符;首字符依次与后面交换,继续递归剩余字符
for j := i; j < length; j++ {
_, ok := strMap[string(strByte[j])]
if !ok {
strMap[string(strByte[j])] = 1
if j != i {
strByte[i], strByte[j] = strByte[j], strByte[i]
}
permutationHandler(strByte, i+1, result)
if j != i {
strByte[i], strByte[j] = strByte[j], strByte[i]
}
}
}
} else {
*result = append(*result, string(strByte))
}
}


func Perm(a []rune, f func([]rune)) {
perm(a, f, 0)
}

func perm(a []rune, f func([]rune), i int) {
length := len(a)
if i != length {
strMap := make(map[string]int)
for j := i; j < length; j++ {
_, ok := strMap[string(a[j])]
if !ok {
strMap[string(a[j])] = 1
if j != i {
a[i], a[j] = a[j], a[i]
}
perm(a, f, i+1)
if j != i {
a[i], a[j] = a[j], a[i]
}
}
}
} else {
f(a)
}
}


func main() {
res1 := permutation1("ABC")
fmt.Println(res1)

res2 := permutation2("ABC")
fmt.Println(res2)

Perm([]rune("ABC"), func(a []rune) {
fmt.Println(string(a))
})
}

二、参考


随机生成字符串

一、代码

  1. main_test.go
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
package main

import (
"fmt"
"math/rand"
"strings"
"testing"
"time"
"unsafe"
)

var letters1 = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func randStr1(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters1[rand.Intn(len(letters1))]
}
return string(b)
}

func TestApproach1(t *testing.T) {
rand.Seed(time.Now().UnixNano())
fmt.Println(randStr1(10))
}

func BenchmarkApproach1(b *testing.B) {
rand.Seed(time.Now().UnixNano())
for i := 0; i < b.N; i++ {
_ = randStr1(10)
}
}


const letters2 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func randStr2(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letters2[rand.Intn(len(letters2))]
}
return string(b)
}

func TestApproach2(t *testing.T) {
rand.Seed(time.Now().UnixNano())

fmt.Println(randStr2(10))
}

func BenchmarkApproach2(b *testing.B) {
rand.Seed(time.Now().UnixNano())
for i := 0; i < b.N; i++ {
_ = randStr2(10)
}
}



const letters3 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func randStr3(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letters3[rand.Int63() % int64(len(letters3))]
}
return string(b)
}

func TestApproach3(t *testing.T) {
rand.Seed(time.Now().UnixNano())

fmt.Println(randStr3(10))
}

func BenchmarkApproach3(b *testing.B) {
rand.Seed(time.Now().UnixNano())
for i := 0; i < b.N; i++ {
_ = randStr3(10)
}
}



const letters4 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
// 6 bits to represent a letters4 index
letterIdBits = 6
// All 1-bits as many as letterIdBits
letterIdMask = 1 <<letterIdBits - 1
)

func randStr4(n int) string {
b := make([]byte, n)
for i := range b {
if idx := int(rand.Int63() & letterIdMask); idx < len(letters4) {
b[i] = letters4[idx]
i++
}
}
return string(b)
}

func TestApproach4(t *testing.T) {
rand.Seed(time.Now().UnixNano())

fmt.Println(randStr4(10))
}

func BenchmarkApproach4(b *testing.B) {
rand.Seed(time.Now().UnixNano())
for i := 0; i < b.N; i++ {
_ = randStr4(10)
}
}



const letters5 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
// 6 bits to represent a letter index
letterIdBits5 = 6
// All 1-bits as many as letterIdBits
letterIdMask5 = 1<<letterIdBits5 - 1
letterIdMax5 = 63 / letterIdBits5
)

func randStr5(n int) string {
b := make([]byte, n)
// A rand.Int63() generates 63 random bits, enough for letterIdMax letters5!
for i, cache, remain := n-1, rand.Int63(), letterIdMax5; i >= 0; {
if remain == 0 {
cache, remain = rand.Int63(), letterIdMax5
}
if idx := int(cache & letterIdMask); idx < len(letters5) {
b[i] = letters5[idx]
i--
}
cache >>= letterIdBits
remain--
}
return string(b)
}

func TestApproach5(t *testing.T) {
rand.Seed(time.Now().UnixNano())

fmt.Println(randStr5(10))
}

func BenchmarkApproach5(b *testing.B) {
rand.Seed(time.Now().UnixNano())
for i := 0; i < b.N; i++ {
_ = randStr5(10)
}
}



const letters6 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var src = rand.NewSource(time.Now().UnixNano())
const (
// 6 bits to represent a letter index
letterIdBits6 = 6
// All 1-bits as many as letterIdBits6
letterIdMask6 = 1<<letterIdBits6 - 1
letterIdMax6 = 63 / letterIdBits6
)

func randStr6(n int) string {
b := make([]byte, n)
// A rand.Int63() generates 63 random bits, enough for letterIdMax6 letters6!
for i, cache, remain := n-1, src.Int63(), letterIdMax6; i >= 0; {
if remain == 0 {
cache, remain = src.Int63(), letterIdMax6
}
if idx := int(cache & letterIdMask6); idx < len(letters6) {
b[i] = letters6[idx]
i--
}
cache >>= letterIdBits6
remain--
}
return string(b)
}

func TestApproach6(t *testing.T) {
fmt.Println(randStr6(10))
}

func BenchmarkApproach6(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = randStr6(10)
}
}



const letters7 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var src7 = rand.NewSource(time.Now().UnixNano())
const (
// 6 bits to represent a letter index
letterIdBits7 = 6
// All 1-bits as many as letterIdBits7
letterIdMask7 = 1<<letterIdBits7 - 1
letterIdMax7 = 63 / letterIdBits7
)

func randStr7(n int) string {
sb := strings.Builder{}
sb.Grow(n)
// A rand.Int63() generates 63 random bits, enough for letterIdMax7 letters7!
for i, cache, remain := n-1, src7.Int63(), letterIdMax7; i >= 0; {
if remain == 0 {
cache, remain = src7.Int63(), letterIdMax7
}
if idx := int(cache & letterIdMask7); idx < len(letters7) {
sb.WriteByte(letters7[idx])
i--
}
cache >>= letterIdBits7
remain--
}
return sb.String()
}

func TestApproach7(t *testing.T) {
fmt.Println(randStr7(10))
}

func BenchmarkApproach7(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = randStr7(10)
}
}



const letters8 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
var src8 = rand.NewSource(time.Now().UnixNano())
const (
// 6 bits to represent a letter index
letterIdBits8 = 6
// All 1-bits as many as letterIdBits8
letterIdMask8 = 1<<letterIdBits8 - 1
letterIdMax8 = 63 / letterIdBits8
)

func randStr8(n int) string {
b := make([]byte, n)
// A rand.Int63() generates 63 random bits, enough for letterIdMax8 letters8!
for i, cache, remain := n-1, src8.Int63(), letterIdMax8; i >= 0; {
if remain == 0 {
cache, remain = src8.Int63(), letterIdMax8
}
if idx := int(cache & letterIdMask8); idx < len(letters8) {
b[i] = letters8[idx]
i--
}
cache >>= letterIdBits8
remain--
}
return *(*string)(unsafe.Pointer(&b))
}

func TestApproach8(t *testing.T) {
fmt.Println(randStr8(10))
}

func BenchmarkApproach8(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = randStr8(10)
}
}
  1. 运行go test -bench=. -benchmem

二、参考

  1. 参考一
  2. 参考二