go入门

11/28/2022

# GO

gprc、grom、gin、go-micro...

# 指针

指针 (opens new window)

// * &
// 方法返回值为*T时,会发生内存逃逸。c语言则会error
func main() {
	namePtr := new(string)
	*namePtr = "Feng"
	fmt.Println("namePtr :", namePtr)
	fmt.Println("namePtr 值:", *namePtr)

	name2 := "wwww"

	name2Ptr := &name2

	fmt.Println("name2Ptr :", name2Ptr)
	fmt.Println("name2 值:", *name2Ptr)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# go/协程

# Go exit

# channel

无缓冲

有缓冲

for range

单向和双向管道

Select case

# Server Demo

package socket

import (
	"fmt"
	"net"
	"strings"
)

func main() {
	// 创建监听
	ip := "127.0.0.1"
	port := "8848"
	address := fmt.Sprintf("%s:%d", ip, port)
	listen, err := net.Listen("tcp", address)
	if err != nil {
		fmt.Println("register === err.Error()", err)
	}
	// Accept() (Conn, error)
	conn, err := listen.Accept()
	if err != nil {
		fmt.Println("accept === err.Error()", err)
	}

	buf := make([]byte, 1024)
	// Read(b []byte) (n int, err error)
	cnt, err := conn.Read(buf)

	if err != nil {
		fmt.Println("conn.Read === err.Error()", err)
	}

	fmt.Println("收到客户端--->的数据,长度:", cnt, "数据:", string(buf))
	serRes := strings.ToUpper(string(buf))
	cnt, err = conn.Write([]byte(serRes))
	fmt.Println("服务端发送--->客户端的数据,长度:", cnt, "数据:", serRes)

	conn.Close()
	
}
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

# Client

package main

import (
	"fmt"
	"net"
	"time"
)

func main() {

	con, err := net.Dial("tcp", ":8848")
	if err != nil {
		fmt.Println("net.Dia === err.Error()", err)
		return
	}

	fmt.Println("client连接建立成功")
	for {
		sendData := "Hello, world"
		cnt, err := con.Write([]byte(sendData))

		if err != nil {
			fmt.Println("con.Write === err.Error()", err)
			return
		}

		fmt.Println("客户端发送--->服务端的数据,长度:", cnt, "数据:", sendData)

		buf := make([]byte, 1024)
		cnt, err = con.Read(buf)

		if err != nil {
			fmt.Println("con.Read === err.Error()", err)
			return
		}

		fmt.Println("客户端接收<----服务端的数据,长度:", cnt, "数据:", string(buf))
		time.Sleep(1 * time.Second)
	}

	//con.Close()
}

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

# multiply socket Server

package main

import (
   "fmt"
   "net"
   "strings"
)

func main() {
   // 创建监听
   ip := "127.0.0.1"
   port := 8848
   address := fmt.Sprintf("%s:%d", ip, port)
   listen, err := net.Listen("tcp", address)
   if err != nil {
      fmt.Println("register === err.Error()", err)
      return
   }
   fmt.Println("服务端监听ing...")
   for {
      // Accept() (Conn, error)
      conn, err := listen.Accept()
      if err != nil {
         fmt.Println("accept === err.Error()", err)
      }
      go handle(conn)
   }

}

func handle(conn net.Conn) {
   fmt.Println("建立连接成功===", conn.RemoteAddr())
   for {

      buf := make([]byte, 1024)
      // Read(b []byte) (n int, err error),阻塞
      cnt, err := conn.Read(buf)

      if err != nil {
         fmt.Println("conn.Read === err.Error()", err)
      }

      fmt.Println("收到客户端--->的数据,长度:", cnt, "数据:", string(buf))
      serRes := strings.ToUpper(string(buf))
      cnt, err = conn.Write([]byte(serRes))
      fmt.Println("服务端发送--->客户端的数据,长度:", cnt, "数据:", serRes)
   }
   // _ = conn.Close()

}
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

# Http-client

package main

import (
   "fmt"
   "io/ioutil"
   "net/http"
)

func main() {
   client := http.Client{}
   resp, _ := client.Get("https://blog.alane.top")
   body := resp.Body
   all, _ := ioutil.ReadAll(body)
   fmt.Println("====", string(all))

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# http-server

package main

import (
   "fmt"
   "io"
   "net/http"
)

func main() {

   // 路由,func回调函数
   http.HandleFunc("/user", func(writer http.ResponseWriter, request *http.Request) {
      _, _ = io.WriteString(writer, "user返回")
   })

   if err := http.ListenAndServe("127.0.0.1:8080", nil); err != nil {
      fmt.Println("server error ===", err)
      return
   }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# json序列化

package main

import (
   "encoding/json"
   "fmt"
)

type Student struct {
   Name   string
   Age    int
   Id     int64
   gender int
}

func main() {

   feng := Student{
      Id:     1,
      Name:   "feng",
      Age:    18,
      gender: 1, // 小写 json序列化会忽略
   }
   encodeInfo, err := json.Marshal(&feng)
   if err != nil {
      fmt.Println("json.Marshal(&feng)===", err)
      return
   }
   fmt.Println("encodeInfo", string(encodeInfo))

   var feng2 Student

   if err := json.Unmarshal(encodeInfo,&feng2); err != nil {
      fmt.Println("json.Unmarshal(&feng2)===", err)
      return
   }
   fmt.Println("feng2",feng2)
}
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

Print...

encodeInfo {"Name":"feng","Age":18,"Id":1}
feng2 {feng 18 1 0}
1
2

# Json label

package main

import (
   "encoding/json"
   "fmt"
)

type Teacher struct {
   Name    string `json:"-"`
   Age     int    `json:"age,string"`
   Id      int64
   gender  int
   Address string `json:"address,omitempty""`
}

func main() {
   tea := Teacher{
      Name:    "tea",
      Age:     19,
      Id:      1,
      gender:  2,
      Address: "",
   }

   encodeInfo, err := json.Marshal(&tea)
   if err != nil {
      fmt.Println("json.Marshal(&tea)===", err)
      return
   }
   fmt.Println("encodeInfo", string(encodeInfo))
}
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

# 聊天室实现

# 需求

1. 上线下线
2. 聊天
3. 查询当前聊天室的用户名
4. 可以修改自己的名字rename
5. 超时退出 
1
2
3
4
5

# 技术点分析

  • socket、tcp编程
  • map
    • 存储用户
    • 遍历
    • map添加删除
  • go程。通道
  • Select模型(超时退出、主动退出)
  • 定时器

# 实现步骤

  • socket

  • 定义user

  • 定义map

  • 定义message通道

  • 监听动作

image-20221127144654942

# 测试tcp工具netcat

mac安装
brew install netcat
nc 127.0.0.1 8080 // 创建客户端
1
2
3

image-20221127155624212