Last Updated: September 22, 2018
· 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."

6 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: http://loige.com/simple-echo-server-written-in-go-dockerized

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?


11 months 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.

10 months 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.

10 months ago ·