Last Updated: September 25, 2020
· donutdan4114

Creating a simple TCP server in Go

package main

import (

const (
    CONN_HOST = "localhost"
    CONN_PORT = "3333"
    CONN_TYPE = "tcp"

func main() {
    // Listen for incoming connections.
    l, err := net.Listen(CONN_TYPE, CONN_HOST+":"+CONN_PORT)
    if err != nil {
        fmt.Println("Error listening:", err.Error())
    // Close the listener when the application closes.
    defer l.Close()
    fmt.Println("Listening on " + CONN_HOST + ":" + CONN_PORT)
    for {
        // Listen for an incoming connection.
        conn, err := l.Accept()
        if err != nil {
            fmt.Println("Error accepting: ", err.Error())
        // Handle connections in a new goroutine.
        go handleRequest(conn)

// Handles incoming requests.
func handleRequest(conn net.Conn) {
  // Make a buffer to hold incoming data.
  buf := make([]byte, 1024)
  // Read the incoming connection into the buffer.
  reqLen, err := conn.Read(buf)
  if err != nil {
    fmt.Println("Error reading:", err.Error())
  // Send a response back to person contacting us.
  conn.Write([]byte("Message received."))
  // Close the connection when you're done with it.

If you build this and run it, you'll have a simple TCP server running on port 3333.
To test your server, send some raw data to that port:

echo -n "test out the server" | nc localhost 3333

You should get a response:

"Message received."

7 Responses
Add your response

I just wrote an article that describes how to "dockerize" a Go app very similar on the one you described here. Obviously I mentioned this post. Let me know if you like it:

over 1 year ago ·

Just a little bug:

$ go run tcp_server.go


.\tcp_server.go:42: reqLen declared and not used


over 1 year ago ·

Change unused variables with underscore ( _ ). Compiler won't complain.

over 1 year ago ·

Hi sir. would you please help me with this problem?

over 1 year ago ·

Hello Daniel!

I do not think it is good practice to require the handler to close the connection. It should be closed by the caller.

over 1 year ago ·

And I just realise, the use of ALL_UPPER_CASE_CONSTANTS is not idiomatic go. Constants in go are named just as everything in go using camelcase, where the first letters case indicates wether the constant is exported or not from the package. Exporting from main does not make sense, since you can not import a package named main.

over 1 year ago ·

Can you update your example to set CONN_HOST to "". This way another computer can make a connection without too much hassle

over 1 year ago ·