TCP 服务器

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. )
  7. func main() {
  8. // net 包提供方便的工具用于 network I/O 开发,包括TCP/IP, UDP 协议等。
  9. // Listen 函数会监听来自 8080 端口的连接,返回一个 net.Listener 对象。
  10. li, err := net.Listen("tcp", ":8080")
  11. // 错误处理
  12. if err != nil {
  13. log.Panic(err)
  14. }
  15. // 释放连接,通过 defer 关键字可以让连接在函数结束前进行释放
  16. // 这样可以不关心释放资源的语句位置,增加代码可读性
  17. defer li.Close()
  18. // 不断循环,不断接收来自客户端的请求
  19. for {
  20. // Accept 函数会阻塞程序,直到接收到来自端口的连接
  21. // 每接收到一个链接,就会返回一个 net.Conn 对象表示这个连接
  22. conn, err := li.Accept()
  23. if err != nil {
  24. log.Println(err)
  25. }
  26. // 字符串写入到客户端
  27. fmt.Fprintln(conn, "Hello from TCP server")
  28. conn.Close()
  29. }
  30. }

TCP 客户端

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "net"
  7. )
  8. func main() {
  9. // net 包的 Dial 函数能创建一个 TCP 连接
  10. conn, err := net.Dial("tcp", ":8080")
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. // 别忘了关闭连接
  15. defer conn.Close()
  16. // 通过 ioutil 来读取连接中的内容,返回一个 []byte 类型的对象
  17. byte, err := ioutil.ReadAll(conn)
  18. if err != nil {
  19. log.Println(err)
  20. }
  21. // []byte 类型的数据转成字符串型,再将其打印输出
  22. fmt.Println(string(byte))
  23. }

HTTP服务器

  1. package main
  2. import "net/http"
  3. func main() {
  4. http.ListenAndServe(":8080", nil)
  5. }

Go 是通过一个函数 ListenAndServe 来处理这些事情的,这个底层其实这样处理的:初始化一个server 对象,然后调用了 net.Listen(“tcp”, addr),也就是底层用 TCP 协议搭建了一个服务,然后监控我们设置的端口。

查文档可以发现 http 包下的 ListenAndServe 函数第一个参数是地址,而第二个是 Handler 类型的参数,我们想要显示内容就要在第二个参数下功夫。

  1. func ListenAndServe(addr string, handler Handler) error

再次查文档,得知 Handler 是一个接口,也就是说只要我们给某一个类型创建 ServeHTTP(ResponseWriter, *Request) 方法,就能符合接口的要求,也就实现了接口。
Go 网络编程简介 - 图1

HandleFun

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. )
  6. func boy(w http.ResponseWriter, r *http.Request) {
  7. fmt.Fprintln(w, "I love you!!!")
  8. }
  9. func girl(w http.ResponseWriter, r *http.Request) {
  10. fmt.Fprintln(w, "hehe.")
  11. }
  12. func foo(w http.ResponseWriter, r *http.Request) {
  13. fmt.Fprintln(w, "Men would stop talking and women would shed tears when they see this.")
  14. }
  15. func main() {
  16. http.HandleFunc("/boy/", boy)
  17. http.HandleFunc("/girl/", girl)
  18. http.HandleFunc("/", foo)
  19. http.ListenAndServe(":8080", nil)
  20. }

HandleFunc
http 包里面还定义了一个类型 http.HandlerFunc,该类型默认实现 Handler 接口,我们可以通过 HandlerFunc(foo) 的方式来实现类型强转,使 foo 也实现了 Handler 接口。
Go 网络编程简介 - 图2

  1. package main
  2. import (
  3. "fmt"
  4. "net/http"
  5. )
  6. func boy(w http.ResponseWriter, r *http.Request) {
  7. fmt.Fprintln(w, "I love you!!!")
  8. }
  9. func girl(w http.ResponseWriter, r *http.Request) {
  10. fmt.Fprintln(w, "hehe.")
  11. }
  12. func foo(w http.ResponseWriter, r *http.Request) {
  13. fmt.Fprintln(w, "Men would stop talking and women would shed tears when they see this.")
  14. }
  15. func main() {
  16. // http.Handler() 的第二个参数是要实现了 Handler 接口的类型
  17. // 可以通过类型强转来重新使用该函数来实现
  18. http.Handle("/boy/", http.HandlerFunc(boy))
  19. http.Handle("/girl/", http.HandlerFunc(girl))
  20. http.Handle("/", http.HandlerFunc(foo))
  21. http.ListenAndServe(":8080", nil)
  22. }

Go 网络编程简介 - 图3