我试图在Go中创建服务器并连接到它,但是当服务器开始运行时,由于启动服务器的功能似乎正在阻塞,因此未调用任何功能。我尝试使用goroutine在后台运行服务器,以便可以执行其他代码,但这也不起作用。我遇到了我不明白的错误
紧急:运行时错误:无效的内存地址或nil指针 解引用[signal SIGSEGV:细分违规代码= 0x1 addr = 0x18 pc = 0x496757]
这是我的服务器代码
func RunServer(port string) {
fmt.Println("Launching server...")
ln, err := net.Listen("tcp", port)
conn, _ := ln.Accept()
// run loop forever (or until ctrl-c)
for {
// will listen for message to process ending in newline (\n)
message, _ := bufio.NewReader(conn).ReadString('\n')
// output message received
fmt.Print("Message Received:", string(message))
// sample process for string received
newmessage := strings.ToUpper(message)
// send new string back to client
conn.Write([]byte(newmessage + "\n"))
}
}
这是客户端的代码。
func createInitalClient(port int) {
// run server then create a client that connects to it
portToRunOn := fmt.Sprintf("%s%d", ":", port)
go RunServer(portToRunOn)
}
func main() {
createInitalClient(5000)
// connect to this socket
conn, _ := net.Dial("tcp", "127.0.0.1:5000")
for {
// read in input from stdin
reader := bufio.NewReader(os.Stdin)
fmt.Print("Text to send: ")
text, _ := reader.ReadString('\n')
// send to socket
fmt.Fprintf(conn, text+"\n")
// listen for reply
message, _ := bufio.NewReader(conn).ReadString('\n')
fmt.Print("Message from server: " + message)
}
}
我是做对了还是有其他方法来做我想做的事情?我有点不愿使用goroutine,因为在我的情况下引入异步行为可能是错误的。
编辑1 :由于客户端试图在服务器启动之前尝试连接服务器,因此似乎发生了此错误。
编辑2 :我(可能已经)通过在服务器中添加一个布尔通道来解决此问题,该布尔通道会在侦听器开始接受连接之前立即返回true。然后,仅当来自通道的值为true时,客户端才连接到服务器。在这种情况下,我不确定这是否是正确的解决方法,但它似乎可以正常工作。
答案 0 :(得分:2)
您的服务器在goroutine中启动,该goroutine由Go运行时异步生成,并且需要一些时间来计划和执行。具体来说,运行时不会在继续执行main
函数之前等待服务器goroutine启动。
您要么需要:
让您的客户端连接尝试重复连接,直到接受连接为止–实际上是轮询服务器的就绪状态。例如:
// Predeclare "conn" to ensure it remains in scope outside the loop
var conn net.Conn
for {
var err error
conn, err = net.Dial("tcp", "127.0.0.1:5000")
// Failed connection, try again in a second.
// TODO: limit the number of attempts before giving up.
if err != nil {
time.Sleep(time.Second)
continue
}
// Connected successfully. Continue.
break
}
// do something with "conn"
正如您对问题的评论所指出的那样,您的代码在多个位置都忽略了错误值。
请不要在实际的生产代码中执行此操作。返回错误是有原因的,并且可能表明代码外部存在问题,导致您的程序无法正常继续执行。您需要检查错误值,并在返回错误值时采取适当的措施。如果返回的error
不是nil
,则从函数调用返回的其他值(尤其是标准库中的所有值)不太可能有意义。
是的,您最终会写很多if err != nil
。这是预料之中的,在某些情况下可以采用多种模式来避免使代码看起来过于重复。