0% found this document useful (0 votes)
5 views

Go Programming Language Tutorial (Part 3)

A Go Programming Language Tutorial (Part 3)

Uploaded by

eowug
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

Go Programming Language Tutorial (Part 3)

A Go Programming Language Tutorial (Part 3)

Uploaded by

eowug
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 8

Go Programming Language Tutorial (Part 3)

This tutorial focuses on interfaces, testing techniques, error handling best practices, concurrency
patterns, and package development.

1. Interfaces
What is an Interface?
An interface in Go defines a set of method signatures. A type implements an interface if it defines those
methods.

Defining and Using an Interface


go
Copy code
package main

import "fmt"

// Define an interface
type Shape interface {
Area() float64
Perimeter() float64
}

// Circle type
type Circle struct {
Radius float64
}

func (c Circle) Area() float64 {


return 3.14 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {


return 2 * 3.14 * c.Radius
}

// Rectangle type
type Rectangle struct {
Length, Width float64
}

func (r Rectangle) Area() float64 {


return r.Length * r.Width
}

func (r Rectangle) Perimeter() float64 {


return 2 * (r.Length + r.Width)
}

func main() {
// Polymorphism with interface
shapes := []Shape{
Circle{Radius: 5},
Rectangle{Length: 10, Width: 4},
}

for _, shape := range shapes {


fmt.Println("Area:", shape.Area(), "Perimeter:", shape.Perimeter())
}
}

2. Advanced Error Handling


Custom Error Types
Create custom error types to provide more context.
go
Copy code
package main

import (
"fmt"
)

// Custom error type


type DivideError struct {
Dividend, Divisor int
}

func (e DivideError) Error() string {


return fmt.Sprintf("cannot divide %d by %d", e.Dividend, e.Divisor)
}

func divide(a, b int) (int, error) {


if b == 0 {
return 0, DivideError{Dividend: a, Divisor: b}
}
return a / b, nil
}

func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Println("Result:", result)
}
}
3. Advanced Testing
Table-Driven Tests
Table-driven testing is an efficient way to test multiple cases.
go
Copy code
package main

import "testing"

// Function to test
func Add(a, b int) int {
return a + b
}

func TestAdd(t *testing.T) {


tests := []struct {
name string
a, b int
expected int
}{
{"Add positive numbers", 1, 2, 3},
{"Add negatives", -1, -2, -3},
{"Add mixed", 10, -5, 5},
}

for _, tt := range tests {


t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Expected %d, got %d", tt.expected, result)
}
})
}
}

Mocking with Interfaces


Use interfaces to create mock implementations for testing.
go
Copy code
package main

import (
"fmt"
"testing"
)

// Service interface
type Service interface {
GetData() string
}

// Real implementation
type RealService struct{}
func (r RealService) GetData() string {
return "Real Data"
}

// Mock implementation for testing


type MockService struct{}

func (m MockService) GetData() string {


return "Mock Data"
}

// Function using the service


func Process(service Service) string {
return service.GetData()
}

func TestProcess(t *testing.T) {


mock := MockService{}
result := Process(mock)
if result != "Mock Data" {
t.Errorf("Expected 'Mock Data', got '%s'", result)
}
}

4. Concurrency Patterns
Worker Pools
Worker pools distribute tasks among multiple Goroutines.
go
Copy code
package main

import (
"fmt"
"sync"
)

// Worker function
func worker(id int, jobs <-chan int, results chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
for job := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, job)
results <- job * 2
}
}

func main() {
jobs := make(chan int, 5)
results := make(chan int, 5)

var wg sync.WaitGroup
// Start workers
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, jobs, results, &wg)
}

// Send jobs
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)

// Wait for workers to finish


wg.Wait()
close(results)

// Collect results
for result := range results {
fmt.Println("Result:", result)
}
}

Select Statement
Use select to wait on multiple channels.
go
Copy code
package main

import (
"fmt"
"time"
)

func main() {
ch1 := make(chan string)
ch2 := make(chan string)

go func() {
time.Sleep(2 * time.Second)
ch1 <- "Channel 1"
}()

go func() {
time.Sleep(1 * time.Second)
ch2 <- "Channel 2"
}()

for i := 0; i < 2; i++ {


select {
case msg1 := <-ch1:
fmt.Println("Received:", msg1)
case msg2 := <-ch2:
fmt.Println("Received:", msg2)
}
}
}
5. Package Development
Creating a Custom Package
1. Create the following structure:
go
Copy code
mypackage/
├── main.go
├── math/
│ └── math.go

2. Define a package in math/math.go:


go
Copy code
package math

// Function in the package


func Add(a, b int) int {
return a + b
}

3. Use the package in main.go:


go
Copy code
package main

import (
"fmt"
"mypackage/math"
)

func main() {
fmt.Println("Sum:", math.Add(2, 3))
}

4. Build and run:


bash
Copy code
go run main.go

6. Building HTTP APIs


Basic HTTP API
go
Copy code
package main

import (
"encoding/json"
"net/http"
)

type User struct {


ID int `json:"id"`
Name string `json:"name"`
}

func getUser(w http.ResponseWriter, r *http.Request) {


user := User{ID: 1, Name: "John Doe"}
json.NewEncoder(w).Encode(user)
}

func main() {
http.HandleFunc("/user", getUser)
http.ListenAndServe(":8080", nil)
}

7. Managing Dependencies
Using go mod
1. Initialize a module:
bash
Copy code
go mod init example.com/myproject

2. Add dependencies:
bash
Copy code
go get github.com/gin-gonic/gin

3. Example with the gin package:


go
Copy code
package main

import "github.com/gin-gonic/gin"

func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "pong"})
})
r.Run(":8080")
}
This tutorial explores key intermediate and advanced Go features. It prepares you for real-world Go
development, including creating reusable packages, managing dependencies, and building scalable
applications. Dive deeper into advanced concurrency, reflection, and Go's standard library for further
learning!

You might also like