I'm a Go (and programming in general) newbie and the task was to program a Go server that would accept incoming messages, take each line, reverse its order and case and send it back. Besides doing that I also wrote a client (just for the hell of it and to help me test my server). I wonder if some things could've been done better and just want feedback on my code.
I'm particularly interested in proper usage of those break
statements I used to forcefully finish Scan()
loops and if I really have to send end of line symbols from my client as a hardcoded measure (rather than use some other function that automatically adds end of line symbols when reading input).
Server:
func reverse(s string) string {
runes := []rune(s)
for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
runes[i], runes[j] = runes[j], runes[i]
}
return string(runes)
}
func swapCase(s string) string {
return strings.Map(func(r rune) rune {
switch {
case unicode.IsLower(r):
return unicode.ToUpper(r)
case unicode.IsUpper(r):
return unicode.ToLower(r)
}
return r
}, s)
}
func handleServerConnection(c net.Conn, i int) {
for {
// scan message
scanner := bufio.NewScanner(c)
for scanner.Scan() {
msg := scanner.Text()
log.Printf("Client %v sends: %v", i, msg)
msgNew := swapCase(reverse((msg)))
c.Write([]byte(msgNew + "\n"))
log.Printf("Client %v receives: %v", i, msgNew)
fmt.Println("---")
}
if errRead := scanner.Err(); errRead != nil {
log.Printf("Client %v disconnected...", i)
fmt.Println("---")
return
}
}
}
func main() {
log.Println("Server launched...")
// listen on all interfaces
ln, _ := net.Listen("tcp", ":9999")
i := 0
for {
// accept connection on port
c, _ := ln.Accept()
i++
log.Printf("Client %v connected...", i)
fmt.Println("---")
// handle the connection
go handleServerConnection(c, i)
}
}
Client:
func main() {
i := 0 // connection index
// connect to server
for {
connect:
c, errConn := net.Dial("tcp", "127.0.0.1:9999")
if errConn != nil {
continue
} else {
i++
if i <= 1 {
log.Println("Connected to server...")
fmt.Println("---")
} else {
log.Println("Reconnected to server...")
fmt.Println("---")
}
}
for {
// read in input from stdin
scannerStdin := bufio.NewScanner(os.Stdin)
fmt.Print("Server message: ")
for scannerStdin.Scan() {
text := scannerStdin.Text()
fmt.Println("---")
// send to server
_, errWrite := fmt.Fprintf(c, text+"\n")
if errWrite != nil {
log.Println("Server offline, attempting to reconnect...")
goto connect
}
log.Print("Server receives: " + text)
break
}
// listen for reply
scannerConn := bufio.NewScanner(c)
for scannerConn.Scan() {
log.Println("Server sends: " + scannerConn.Text())
break
}
if errReadConn := scannerStdin.Err(); errReadConn != nil {
log.Printf("Read error: %T %+v", errReadConn, errReadConn)
return
}
fmt.Println("---")
}
}
}