面试题答案
一键面试1. 使用Go语言构建基于I/O复用的高效网络服务器
在Go语言中,标准库 net
包已经为我们提供了基于I/O复用技术(在不同操作系统下会使用对应高效的I/O复用机制,如Linux下epoll,FreeBSD下kqueue等)的实现,使得构建高效网络服务器变得相对简单。
下面是一个简单的TCP服务器示例,用于处理多个并发连接:
package main
import (
"fmt"
"net"
)
func handleConnection(conn net.Conn) {
defer conn.Close()
buffer := make([]byte, 1024)
for {
n, err := conn.Read(buffer)
if err != nil {
fmt.Println("Read error:", err)
return
}
data := buffer[:n]
fmt.Println("Received:", string(data))
_, err = conn.Write(data)
if err != nil {
fmt.Println("Write error:", err)
return
}
}
}
func main() {
listen, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Println("Listen error:", err)
return
}
defer listen.Close()
for {
conn, err := listen.Accept()
if err != nil {
fmt.Println("Accept error:", err)
continue
}
go handleConnection(conn)
}
}
在上述代码中:
net.Listen
函数用于监听指定地址和端口,底层会使用操作系统的I/O复用机制来高效处理连接请求。listen.Accept
用于接受新的连接。每次调用Accept
时,如果当前没有新连接,它会阻塞等待,直到有新连接到来。- 对于每个新连接,我们使用
go
关键字启动一个新的goroutine来处理该连接,从而实现并发处理多个连接。
2. Go语言中实现I/O复用的相关标准库函数及使用场景
net.Listen
:- 函数签名:
func Listen(network, address string) (Listener, error)
- 使用场景:用于在指定的网络协议(如
tcp
、udp
、unix
等)和地址上监听传入的连接。常用于构建网络服务器,如HTTP服务器、TCP服务器等。
- 函数签名:
Listener.Accept
:- 函数签名:
func (l Listener) Accept() (Conn, error)
- 使用场景:由
net.Listen
返回的Listener
调用,用于接受新的连接。每次调用会阻塞直到有新连接到达,返回一个Conn
用于与客户端进行通信。
- 函数签名:
Conn.Read
和Conn.Write
:- 函数签名:
func (c Conn) Read(b []byte) (n int, err error)
和func (c Conn) Write(b []byte) (n int, err error)
- 使用场景:用于在已建立的连接上进行数据的读取和写入操作。
Read
方法会阻塞直到有数据可读或者发生错误,Write
方法会阻塞直到数据全部写入或者发生错误。适用于各种需要进行网络数据传输的场景,如HTTP请求响应、自定义协议的数据交互等。
- 函数签名: