Go is a modern programming language that has gained popularity over the years due to its simplicity, concurrency, and performance. It has built-in support for networking and provides an efficient way to build network applications. In this tutorial, we will explore how to build network applications with Go programming.


Prerequisites

To follow this tutorial, you will need:

  • Go installed on your machine
  • Basic knowledge of Go programming language


Creating a TCP Server

A TCP server is a network service that listens for incoming connections from clients. Let's create a simple TCP server that listens on port 9000 and returns the current time to the client.

package main

import (
    "fmt"
    "net"
    "time"
)

func handleConnection(conn net.Conn) {
    defer conn.Close()

    now := time.Now().String()
    conn.Write([]byte(now))
}

func main() {
    ln, err := net.Listen("tcp", ":9000")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer ln.Close()

    fmt.Println("Server started")

    for {
        conn, err := ln.Accept()
        if err != nil {
            fmt.Println(err)
            continue
        }
        go handleConnection(conn)
    }
}


Let's break down the code:

  • We import the net package, which provides the basic networking primitives in Go.
  • The handleConnection function is a handler function that takes a net.Conn object, which represents a network connection, and returns the current time to the client.
  • In the main function, we create a TCP listener using the net.Listen function, which listens on port 9000. We then check for any errors and defer closing the listener when the function returns.
  • We then start an infinite loop to accept incoming connections using the ln.Accept function. When a new connection is accepted, we spawn a new goroutine to handle the connection using the handleConnection function.


Creating a UDP Server

UDP is a connectionless protocol that is used for low-latency, loss-tolerant, and unreliable communication. Let's create a simple UDP server that listens on port 9000 and echoes back the message sent by the client.

package main

import (
    "fmt"
    "net"
)

func handleConnection(conn *net.UDPConn, addr *net.UDPAddr) {
    defer conn.Close()

    buf := make([]byte, 1024)
    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("Received: %s\n", string(buf[:n]))

    _, err = conn.WriteToUDP(buf[:n], addr)
    if err != nil {
        fmt.Println(err)
        return
    }
}

func main() {
    addr, err := net.ResolveUDPAddr("udp", ":9000")
    if err != nil {
        fmt.Println(err)
        return
    }

    conn, err := net.ListenUDP("udp", addr)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer conn.Close()

    fmt.Println("Server started")

    for {
        buf := make([]byte, 1024)
        n, addr, err := conn.ReadFromUDP(buf)
        if err != nil {
            fmt.Println(err)
            continue
        }

        go handleConnection(conn, addr)
    }
}

Let's break down the code:

  • We import the net package, which provides the basic networking primitives in Go.
  • The handleConnection function is a handler function that takes a *net.UDPConn object and a *net.UDPAddr object, which represent the connection and the address of the client. It reads the incoming message from the client, prints it to the console, and sends the message back to the client.
  • In the main function, we first create a UDP address object using the net.ResolveUDPAddr function. We then create a UDP connection using the net.ListenUDP function and pass in the address object. We check for any errors and defer closing the connection when the function returns.
  • We start an infinite loop to handle incoming messages using the conn.ReadFromUDP function. When a new message is received, we spawn a new goroutine to handle the message using the handleConnection function.


Creating a TCP Client

Now that we have created a TCP server, let's create a TCP client that connects to the server and sends a message.

package main

import (
    "fmt"
    "net"
)

func main() {
    conn, err := net.Dial("tcp", "localhost:9000")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer conn.Close()

    message := "Hello, server!"
    _, err = conn.Write([]byte(message))
    if err != nil {
        fmt.Println(err)
        return
    }

    buf := make([]byte, 1024)
    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("Received: %s\n", string(buf[:n]))
}


Let's break down the code:

  • We import the net package, which provides the basic networking primitives in Go.
  • We create a TCP connection to the server using the net.Dial function. We pass in the network type and the server address as arguments. We check for any errors and defer closing the connection when the function returns.
  • We send a message to the server using the conn.Write function.
  • We then read the response from the server using the conn.Read function and print it to the console.


Creating a UDP Client

Finally, let's create a UDP client that sends a message to the server and receives the response.

package main

import (
    "fmt"
    "net"
)

func main() {
    conn, err := net.Dial("udp", "localhost:9000")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer conn.Close()

    message := "Hello, server!"
    _, err = conn.Write([]byte(message))
    if err != nil {
        fmt.Println(err)
        return
    }

    buf := make([]byte, 1024)
    n, err := conn.Read(buf)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Printf("Received: %s\n", string(buf[:n]))
}


Let's break down the code:

  • We import the net package, which provides the basic networking primitives in Go.
  • We create a UDP connection to the server using the net.Dial function. We pass in the network type and the server address as arguments. We check for any errors and defer closing the connection when the function returns.
  • We send a message to the server using the conn.Write function.
  • We then read the response from the server using the conn.Read function and print it to the console.


Conclusion

In this tutorial, we have explored how to build network applications with Go programming. We have created TCP and UDP servers and clients and learned how to handle incoming connections and messages. Go provides a simple and efficient way to build network applications, and its built