TCP 服务器
package main
import (
"fmt"
"log"
"net"
)
func main() {
// net 包提供方便的工具用于 network I/O 开发,包括TCP/IP, UDP 协议等。
// Listen 函数会监听来自 8080 端口的连接,返回一个 net.Listener 对象。
li, err := net.Listen("tcp", ":8080")
// 错误处理
if err != nil {
log.Panic(err)
}
// 释放连接,通过 defer 关键字可以让连接在函数结束前进行释放
// 这样可以不关心释放资源的语句位置,增加代码可读性
defer li.Close()
// 不断循环,不断接收来自客户端的请求
for {
// Accept 函数会阻塞程序,直到接收到来自端口的连接
// 每接收到一个链接,就会返回一个 net.Conn 对象表示这个连接
conn, err := li.Accept()
if err != nil {
log.Println(err)
}
// 字符串写入到客户端
fmt.Fprintln(conn, "Hello from TCP server")
conn.Close()
}
}
TCP 客户端
package main
import (
"fmt"
"io/ioutil"
"log"
"net"
)
func main() {
// net 包的 Dial 函数能创建一个 TCP 连接
conn, err := net.Dial("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
// 别忘了关闭连接
defer conn.Close()
// 通过 ioutil 来读取连接中的内容,返回一个 []byte 类型的对象
byte, err := ioutil.ReadAll(conn)
if err != nil {
log.Println(err)
}
// []byte 类型的数据转成字符串型,再将其打印输出
fmt.Println(string(byte))
}
HTTP服务器
package main
import "net/http"
func main() {
http.ListenAndServe(":8080", nil)
}
Go 是通过一个函数 ListenAndServe 来处理这些事情的,这个底层其实这样处理的:初始化一个server 对象,然后调用了 net.Listen(“tcp”, addr),也就是底层用 TCP 协议搭建了一个服务,然后监控我们设置的端口。
查文档可以发现 http 包下的 ListenAndServe 函数第一个参数是地址,而第二个是 Handler 类型的参数,我们想要显示内容就要在第二个参数下功夫。
func ListenAndServe(addr string, handler Handler) error
再次查文档,得知 Handler 是一个接口,也就是说只要我们给某一个类型创建 ServeHTTP(ResponseWriter, *Request) 方法,就能符合接口的要求,也就实现了接口。
HandleFun
package main
import (
"fmt"
"net/http"
)
func boy(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "I love you!!!")
}
func girl(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hehe.")
}
func foo(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Men would stop talking and women would shed tears when they see this.")
}
func main() {
http.HandleFunc("/boy/", boy)
http.HandleFunc("/girl/", girl)
http.HandleFunc("/", foo)
http.ListenAndServe(":8080", nil)
}
HandleFunc
http 包里面还定义了一个类型 http.HandlerFunc
,该类型默认实现 Handler 接口,我们可以通过 HandlerFunc(foo)
的方式来实现类型强转,使 foo
也实现了 Handler 接口。
package main
import (
"fmt"
"net/http"
)
func boy(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "I love you!!!")
}
func girl(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hehe.")
}
func foo(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Men would stop talking and women would shed tears when they see this.")
}
func main() {
// http.Handler() 的第二个参数是要实现了 Handler 接口的类型
// 可以通过类型强转来重新使用该函数来实现
http.Handle("/boy/", http.HandlerFunc(boy))
http.Handle("/girl/", http.HandlerFunc(girl))
http.Handle("/", http.HandlerFunc(foo))
http.ListenAndServe(":8080", nil)
}