Go 基础 03
- goroutine channel
1 package main 2 3 import ( 4 "fmt" 5 "runtime" 6 ) 7 8 // goroutine 使用 Channel 进行通信 9 // 计算 1000 以内的素数 10 // 一个 goroutine 写,一个 goroutine 读 11 func calc(taskChan chan int, resChan chan int, exitChan chan bool) { 12 for v := range taskChan { 13 flag := true 14 // 判断 v 是否是素数 15 for i := 2; i < v; i++ { 16 if 0 == v%i { 17 // 不是素数的 flag 18 flag = false 19 break 20 } 21 } 22 if flag { 23 // 是素数的情况,就放到 resChan 的 channel 中 24 resChan <- v 25 } 26 } 27 // 这个协程执行完成后,向 exitChan 的channel 中发送一个完成信号 28 exitChan <- true 29 } 30 31 func main() { 32 33 // 获取当前机器 cpu 的核数 34 num := runtime.NumCPU() 35 fmt.Println(num) 36 37 intChan := make(chan int, 1000) 38 resultChan := make(chan int, 1000) 39 // exitChan 装满后,就表示所有协程都执行完成了 40 exitChan := make(chan bool, num) 41 42 // 匿名函数方式,启动一个协程 43 go func() { 44 for i := 0; i < 100000; i++ { 45 intChan <- i 46 } 47 // 关闭 Channel 48 close(intChan) 49 }() 50 // 计算 1000 以内的素数 51 // 一个 goroutine 写,一个 goroutine 读 52 // 通过 for 循环,一共启动 4 个协程 53 // 同时从 intChan 中取数字,计算素数 54 for i := 0; i < num; i++ { 55 go calc(intChan, resultChan, exitChan) 56 } 57 58 // 匿名函数方式,启动一个协程 59 go func() { 60 // 没有完成的 channel 主线程取值时,就阻塞在这里 61 // 直到把 exitChan 都取完,主线程才会继续向下执行 62 for i := 0; i < num; i++ { 63 // 只是取,并不关注取的是什么 64 <-exitChan 65 fmt.Printf("[message] => %d had completed ...\n", i) 66 } 67 // 都取完之后,表示所有的协程都执行完成,就可以关闭 resultChan 的 channel 68 close(resultChan) 69 }() 70 71 for v := range resultChan { 72 fmt.Println(v) 73 } 74 }
- 非阻塞方式从 channel 中读取数据
1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 func main() { 9 var ch chan int 10 ch = make(chan int, 10) 11 ch2 := make(chan int, 10) 12 13 // 向 channel 中存放数据 14 go func() { 15 var i int = 1 16 for { 17 ch <- i 18 time.Sleep(time.Second) 19 ch2 <- i * i 20 time.Sleep(time.Second) 21 i++ 22 } 23 }() 24 25 for { 26 // 当 channel 中的数据被取空时, 27 // 不执行阻塞,而进入 default 分支 28 select { 29 case v := <-ch: 30 fmt.Println(v) 31 case v := <-ch2: 32 fmt.Println(v) 33 default: 34 fmt.Println("get data timeout ...") 35 time.Sleep(time.Second) 36 } 37 } 38 }
- tcp 编程
1 // server.go 2 3 package main 4 5 import ( 6 "fmt" 7 "net" 8 ) 9 10 func main() { 11 fmt.Println("start server...") 12 listen, err := net.Listen("tcp", "0.0.0.0:50000") 13 if err != nil { 14 fmt.Println("listen failed, err:", err) 15 return 16 } 17 for { 18 conn, err := listen.Accept() 19 if err != nil { 20 fmt.Println("accept failed, err:", err) 21 continue 22 } 23 go process(conn) 24 } 25 } 26 func process(conn net.Conn) { 27 defer conn.Close() 28 for { 29 buf := make([]byte, 512) 30 n, err := conn.Read(buf) 31 if err != nil { 32 fmt.Println("read err:", err) 33 return 34 } 35 36 fmt.Printf(string(buf[0:n])) 37 } 38 }
1 // client.go 2 3 package main 4 5 import ( 6 "bufio" 7 "fmt" 8 "net" 9 "os" 10 "strings" 11 ) 12 13 // 客户端的处理流程 14 func main() { 15 // 1- 建立与服务端的连接 16 conn, err := net.Dial("tcp", "localhost:50000") 17 if err != nil { 18 fmt.Println("Error dialing", err.Error()) 19 return 20 } 21 22 // 3- 关闭连接 23 defer conn.Close() 24 25 // 2- 进行数据收发 26 // 从标准输入设备中读取 27 inputReader := bufio.NewReader(os.Stdin) 28 for { 29 // 从标准输入设备中读取以 \n 为结尾的一行 30 input, _ := inputReader.ReadString('\n') 31 // 去掉读到数据的换行和回车 32 trimmedInput := strings.Trim(input, "\r\n") 33 34 // 输入 Q 客户端就退出了 35 if trimmedInput == "Q" { 36 return 37 } 38 // 字符串转为字节切片后,向服务端发送 39 _, err = conn.Write([]byte(trimmedInput)) 40 if err != nil { 41 return 42 } 43 } 44 }
- redis 连接池
1 package main 2 3 import ( 4 "fmt" 5 6 "github.com/garyburd/redigo/redis" 7 ) 8 9 var pool *redis.Pool 10 11 func init() { 12 pool = &redis.Pool{ 13 MaxIdle: 16, 14 MaxActive: 0, 15 IdleTimeout: 300, 16 Dial: func() (redis.Conn, error) { 17 return redis.Dial("tcp", "192.168.56.164:6379") 18 }, 19 } 20 } 21 22 func main() { 23 24 c := pool.Get() 25 // 方法执行后,关闭 redis.Dial 的连接 26 defer c.Close() 27 28 _, err := c.Do("Set", "abc", 100) 29 if err != nil { 30 fmt.Println(err) 31 return 32 } 33 34 r, err := redis.Int(c.Do("Get", "abc")) 35 if err != nil { 36 fmt.Println("get abc failed,", err) 37 return 38 } 39 40 fmt.Println(r) 41 // 关闭连接池已使用的资源 42 pool.Close() 43 }
- http 编程
1 5. // server.go 2 3 package main 4 5 import ( 6 "fmt" 7 "net/http" 8 ) 9 10 func Hello(w http.ResponseWriter, r *http.Request) { 11 // 向本地打印 12 fmt.Println("handle hello") 13 // 向浏览器端发送数据 14 fmt.Fprintf(w, "hello ") 15 } 16 17 func login(w http.ResponseWriter, r *http.Request) { 18 fmt.Println("handle login") 19 fmt.Fprintf(w, "login ") 20 } 21 22 func history(w http.ResponseWriter, r *http.Request) { 23 fmt.Println("handle history") 24 fmt.Fprintf(w, "history ") 25 } 26 27 // 服务端 28 func main() { 29 // 设置路由,处理根目录 30 http.HandleFunc("/", Hello) 31 http.HandleFunc("/user/login", login) 32 http.HandleFunc("/user/history", history) 33 err := http.ListenAndServe("0.0.0.0:8880", nil) 34 if err != nil { 35 fmt.Println("http listen failed") 36 } 37 }
1 // client.go 2 3 package main 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 ) 10 11 // 客户端访问百度 12 func main() { 13 res, err := http.Get("https://www.baidu.com/") 14 if err != nil { 15 fmt.Println("get err:", err) 16 return 17 } 18 19 data, err := ioutil.ReadAll(res.Body) 20 if err != nil { 21 fmt.Println("get data err:", err) 22 return 23 } 24 25 fmt.Println(string(data)) 26 }
- 操作 mysql 数据库
1 package main 2 3 import ( 4 "fmt" 5 6 _ "github.com/go-sql-driver/mysql" 7 "github.com/jmoiron/sqlx" 8 ) 9 10 type Person struct { 11 // 结构体字段 UserId 对应 数据库中的 字段 user_id 12 UserId int `db:"user_id"` 13 Username string `db:"username"` 14 Sex string `db:"sex"` 15 Email string `db:"email"` 16 } 17 18 type Place struct { 19 Country string `db:"country"` 20 City string `db:"city"` 21 TelCode int `db:"telcode"` 22 } 23 24 var Db *sqlx.DB 25 26 func init() { 27 28 database, err := sqlx.Open("mysql", "root:123456@tcp(192.168.56.164:3306)/test") 29 if err != nil { 30 fmt.Println("open mysql failed,", err) 31 return 32 } 33 34 Db = database 35 } 36 37 func main() { 38 39 var person []Person 40 // 查询并将结果返回到 person 数组中 41 err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1) 42 if err != nil { 43 fmt.Println("exec failed, ", err) 44 return 45 } 46 47 fmt.Println("select succ:", person) 48 fmt.Println("select succ:", person[0]) 49 }
( Over )