Golang基础
参考:
- (1条消息) golang在windows平台使用zmq并使用官方文档实现通讯_qurmytywl的博客-CSDN博客
- Go 语言教程 | 菜鸟教程 (runoob.com)
- (1条消息) go操作mysql数据库_山河万里的博客-CSDN博客_go mysql 数据库
- Go语言之搭建文件下载服务端 - 腾讯云开发者社区-腾讯云 (tencent.com)
- Go语言的创建HTTP服务器_DXB2021的博客-CSDN博客_go http服务器
- go中使用protobuf
Windows搭建环境
基础语法
-
格式化输出
package main import ( "fmt" ) func main() { var num = 123 var data = "2020-12-31" var url = "Code=%d&endData=%s" var targetUrl, _ = fmt.Printf(url, num, data) fmt.Println(targetUrl) }
- Golang使用var声明变量
- 返回值中_表示错误结果
-
变量
-
基本数据类型
var a int fmt.Println(a) //var a *int //var a []int //var a map[string] int //var a chan int //var a func(string) int //var a error // error 是接口 intVal := 1 //声明并赋值 fmt.Println(intVal) const ( aa = iota //可以顺序自增的数 b c = "ha" d e = iota )
-
数组&集合
strings := []string{"google", "baidu"} map1 := make(map[int]float32) map1[1] = 1.0 map1[2] = 2.0 map1[3] = 3.0
-
-
控制语句
if a < 20 { fmt.Println("a小于20") } else if a == 20 { fmt.Println("a等于20") } else { fmt.Println("a大于20") } //switch不需要break //switch可以判断interface的类型 var x interface{} switch x.(type) { case nil: fmt.Println("x的类型是nil") case int: fmt.Println("x的类型是int") default: fmt.Println("未知型") } sum := 0 for i := 0; i <= 10; i++ { sum += i } for key, value := range map1 { fmt.Println(key, value) }
-
函数&接口
func max(num1, num2 int) int { var result int if num1 > num2 { result = num1 } else { result = num2 } return result } func swap(x, y *int) { var temp int temp = *x *x = *y *y = temp fmt.Println(*x, *y) } //函数指针类型 type cb func(int) int func testcallback(x int, f cb) { f(x) } /* 定义结构体 */ type Circle struct { radius float64 } func (c Circle) getArea() float64 { return c.radius * c.radius } // 注意如果想要更改成功c的值,这里需要传指针 func (c *Circle) changeRadius(radius float64) { c.radius = radius } // 以下操作将不生效 //func (c Circle) changeRadius(radius float64) { // c.radius = radius //} // 引用类型要想改变值需要传指针 func change(c *Circle, radius float64) { c.radius = radius }
-
错误处理
func Sqrt(f float64) (float64, error) { if f < 0 { return 0, errors.New("math: square root of negative number") } // 实现 } result, err:= Sqrt(-1) if err != nil { fmt.Println(err) }
-
并发
//线程 func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") } func fibonacci(n int, c chan int) { x, y := 0, 1 for i := 0; i < n; i++ { c <- x x, y = y, x+y } close(c) } //通道 func main() { c := make(chan int, 10) go fibonacci(cap(c), c) // range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个 // 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据 // 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不 // 会结束,从而在接收第 11 个数据的时候就阻塞了。 for i := range c { fmt.Println(i) } }
混合编程
//main.go
package main
func main() {
var a = 10
var b = 10
AddPrint(a, b)
}
//hello.go
package main
//int Add(int a, int b){
// return a+b;
//}
import "C"
import "fmt"
func AddPrint(a int, b int) {
fmt.Println(C.Add(C.int(a), C.int(b)))
}
- 需要新建src文件夹
- 需要保留go.mod
- 需要安装gcc
Zmq的使用
-
环境搭建
-
对于经常可随便运行的项目,可以新建一个文件夹,名为main,方便启动多个main函数
-
对于正式的开发项目(只有一个main),创建文件夹名为src
-
使用vcpkg下载zmq,下载的x64-windows版本
vcpkg install cppzmq --triplet=x64-windows
-
环境变量:
GOPROXY=https://goproxy.cn;CGO_CFLAGS=-IC:/Users/20582/vcpkg-master/installed/x64-windows/include;CGO_LDFLAGS=-LC:/Users/20582/vcpkg-master/installed/x64-windows/lib -l:libzmq-mt-4_3_4.lib
用于指定头文件、LIB库文件
-
-
客户端
package main import ( "fmt" zmq "github.com/pebbe/zmq4" ) func main() { zctx, _ := zmq.NewContext() // Socket to talk to server fmt.Printf("Connecting to the server...\n") s, _ := zctx.NewSocket(zmq.REQ) s.Connect("tcp://localhost:5555") // Do 10 requests, waiting each time for a response for i := 0; i < 10; i++ { fmt.Printf("Sending request %d...\n", i) s.Send("Hello", 0) msg, _ := s.Recv(0) fmt.Printf("Recieved reply %d [ %s ]\n", i, msg) } }
-
服务器
package main import ( "log" "time" zmq "github.com/pebbe/zmq4" ) func main() { zctx, _ := zmq.NewContext() s, _ := zctx.NewSocket(zmq.REP) s.Bind("tcp://*:5555") for { // Wait for next request from client msg, _ := s.Recv(0) log.Printf("Recieved %s\n", msg) // Do some 'work' time.Sleep(time.Second * 1) // Send reply back to client s.Send("World", 0) } }
-
protobuf的使用
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 protoc --go_out=. *.proto 也可以将所有的文件统计出来 set proto_list=1.proto 2.proto protoc --go_out=. %proto_list%
package main import ( "fmt" "github.com/golang/protobuf/proto" pb "mmo/demoTest/protobuffDemo/pb" ) func main() { //定义一个Person结构对象 person := &pb.Person{ Name: "wuzi", Age: 16, Emails: []string{"sss@qq.com", "dsa15@qq.com"}, Phones: []*pb.PhoneNumber{ &pb.PhoneNumber{ Number: "131254222", Type: pb.PhoneType_MOBILE, }, &pb.PhoneNumber{ Number: "154512451", Type: pb.PhoneType_WORK, }, }, } //将person对象,就是将protobuf中的message进行序列化,得到一个二进制 //data就是传送的数据,对方需要按照Message Person格式进行解析 p, err := proto.Marshal(person) if err != nil { fmt.Println("marshal err:", err) } fmt.Println("编码后的person:", p) //解码 np := new(pb.Person) err = proto.Unmarshal(p, np) if err != nil { fmt.Println("unmarshal err:", err) } fmt.Println("解码后的person:", np)
}
```
HTTP/HTTPS请求
-
GET/POST
package main import ( "fmt" "io/ioutil" "log" "net/http" ) func helloWorld(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } switch r.Method { case "GET": for k, v := range r.URL.Query() { fmt.Printf("%s: %s\n", k, v) } w.Write([]byte("Received a GET request\n")) case "POST": reqBody, err := ioutil.ReadAll(r.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", reqBody) w.Write([]byte("Received a POST request\n")) default: w.WriteHeader(http.StatusNotImplemented) w.Write([]byte(http.StatusText(http.StatusNotImplemented))) } } func main() { http.HandleFunc("/", helloWorld) http.ListenAndServe(":8000", nil) }
curl -si "http://localhost:8000/?foo=1&bar=2" curl -si POST -d "some data to send" http://localhost:8000/
-
下载请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <a href="download?filename=abc.png">下载</a> </body> </html>
package main import ( "net/http" "html/template" "io/ioutil" ) func showDownloadPage(rw http.ResponseWriter,r *http.Request){ t,_:=template.ParseFiles("template/html/download.html") t.Execute(rw,nil) } func download(rw http.ResponseWriter,r *http.Request){ //获取请求参数 fn:=r.FormValue("filename") //设置响应头 header:=rw.Header() header.Add("Content-Type","application/octet-stream") header.Add("Content-Disposition","attachment;filename="+fn) //使用ioutil包读取文件 b,_:=ioutil.ReadFile("D:/"+fn) //写入到响应流中 rw.Write(b) } func main() { server:=http.Server{Addr:"localhost:8899"} http.HandleFunc("/showdownload",showDownloadPage) http.HandleFunc("/download",download) server.ListenAndServe() }
数据库操作
-
安装:https://dev.mysql.com/downloads/mysql/
-
查看:DBeaver
mysqld --initialize --console mysqld -install net start mysql mysql -u root -p 前面的密码 alter user 'root'@'localhost' identified by '想要设置的密码'; commit; quit;
-
使用go操作
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func errorHandler(err error) { if err != nil { fmt.Println(err.Error()) } } var ( CREATE_TABLE = "CREATE TABLE student(" + "sid INT(10) NOT NULL AUTO_INCREMENT," + "sname VARCHAR(64) NULL DEFAULT NULL," + "age INT(10) DEFAULT NULL,PRIMARY KEY (sid))" + "ENGINE=InnoDB DEFAULT CHARSET=utf8;" ) // 建立数据库连接 func setupConnect() *sql.DB { db, err := sql.Open("mysql", "root:xxxxxx@tcp(118.24.159.133:3306)/student?charset=utf8") errorHandler(err) return db } // 创建表 func CreateTable(db *sql.DB, sql string) { _, err := db.Exec(sql) errorHandler(err) } var INSERT_DATA = `INSERT INTO student(sid,sname,age) VALUES(?,?,?);` // 插入数据 func Insert(db *sql.DB) { db.Exec(INSERT_DATA, 1, "唐僧", 30) } var UPDATE_DATA = `UPDATE student SET age=28 WHERE sname="唐僧";` // 修改数据 func Update(db *sql.DB) { db.Exec(UPDATE_DATA) } var DELETE_DATA = `DELETE FROM student WHERE age>=30` // 删除记录 func Delete(db *sql.DB) { db.Exec(DELETE_DATA) } var DELETE_TABLE = `DROP TABLE student;` // 删除表 func DeleteTable(db *sql.DB) { db.Exec(DELETE_TABLE) } var QUERY_DATA = `SELECT * FROM student;` // 查询数据 func Query(db *sql.DB) { rows, err := db.Query(QUERY_DATA) if err != nil { fmt.Println(err) } for rows.Next() { var name string var id int var age int if err := rows.Scan(&id, &name, &age); err != nil { fmt.Println(err) } fmt.Printf("%s is %d\n", name, age) } } func main() { // 建立数据连接 db := setupConnect() // 创建数据库表 CreateTable(db, CREATE_TABLE) // 插入数据 Insert(db) // 查询数据 Query(db) // 删除数据 Delete(db) // 插入数据 Insert(db) // 修改数据 Update(db) // 查询数据 Query(db) // 删除表 DeleteTable(db) // 关闭数据库连接 db.Close() }