About
RPC ClientDB.go package main
import ( "fmt" "log" "net/rpc" )
type Item struct { Title string Body string }
func main() { var reply Item var db []Item
client, err := rpc.DialHTTP("tcp", "localhost:4040")
if err != nil {
log.Fatal("Connection error: ", err)
}
a := Item{"First", "A first item"}
b := Item{"Second", "A second item"}
c := Item{"Third", "A third item"}
client.Call("API.AddItem", a, &reply)
client.Call("API.AddItem", b, &reply)
client.Call("API.AddItem", c, &reply)
client.Call("API.GetDB", "", &db)
fmt.Println("Database: ", db)
client.Call("API.EditItem", Item{"Second", "A new second item"}, &reply)
client.Call("API.DeleteItem", c, &reply)
client.Call("API.GetDB", "", &db)
fmt.Println("Database: ", db)
client.Call("API.GetByName", "First", &reply)
fmt.Println("first item: ", reply)
} ServerDB.go package main
import ( "log" "net" "net/http" "net/rpc" )
type Item struct { Title string Body string }
type API int
var database []Item
func (a API) GetDB(empty string, reply []Item) error { *reply = database return nil }
func (a API) GetByName(title string, reply Item) error { var getItem Item
for _, val := range database {
if val.Title == title {
getItem = val
}
}
*reply = getItem
return nil
}
func (a API) AddItem(item Item, reply Item) error { database = append(database, item) *reply = item return nil }
func (a API) EditItem(item Item, reply Item) error { var changed Item
for idx, val := range database {
if val.Title == item.Title {
database[idx] = Item{item.Title, item.Body}
changed = database[idx]
}
}
*reply = changed
return nil
}
func (a API) DeleteItem(item Item, reply Item) error { var del Item
for idx, val := range database {
if val.Title == item.Title && val.Body == item.Body {
database = append(database[:idx], database[idx+1:]...)
del = item
break
}
}
*reply = del
return nil
}
func main() { api := new(API) err := rpc.Register(api) if err != nil { log.Fatal("error registering API", err) }
rpc.HandleHTTP()
listener, err := net.Listen("tcp", ":4040")
if err != nil {
log.Fatal("Listener error", err)
}
log.Printf("serving rpc on port %d", 4040)
http.Serve(listener, nil)
if err != nil {
log.Fatal("error serving: ", err)
}
// fmt.Println("initial database: ", database)
// a := Item{"first", "a test item"}
// b := Item{"second", "a second item"}
// c := Item{"third", "a third item"}
// AddItem(a)
// AddItem(b)
// AddItem(c)
// fmt.Println("second database: ", database)
// DeleteItem(b)
// fmt.Println("third database: ", database)
// EditItem("third", Item{"fourth", "a new item"})
// fmt.Println("fourth database: ", database)
// x := GetByName("fourth")
// y := GetByName("first")
// fmt.Println(x, y)
} ClientTime.go package main
import ( "log" "net/rpc" )
type Args struct {}
func main() { // Address to this variable will be sent to the RPC server // Type of reply should be same as that specified on server var reply int64 args := Args{}
// DialHTTP connects to an HTTP RPC server at the specified network
client, err := rpc.DialHTTP("tcp", "0.0.0.0:1234")
if err != nil {
log.Fatal("Client connection error: ", err)
}
// Invoke the remote function GiveServerTime attached to TimeServer pointer
// Sending the arguments and reply variable address to the server as well
err = client.Call("TimeServer.GiveServerTime", args, &reply)
if err != nil {
log.Fatal("Client invocation error: ", err)
}
// Print the reply from the server
log.Printf("%d", reply)
} ServerTime.go package main
import ( "time" "net" "net/http" "net/rpc" "log" )
type Args struct {}
type TimeServer int64
func main() { timeserver := new(TimeServer) // Register the timeserver object upon which the GiveServerTime // function will be called from the RPC server (from the client)
rpc.Register(timeserver)
// Registers an HTTP handler for RPC messages
rpc.HandleHTTP() // ?
// Start listening for the requests on port 1234
listener, err := net.Listen("tcp", ":1234")
if err !=nil {
log.Fatal("Listener error: ", err)
}
// Serve accepts incoming HTTP connections on the listener l,creating
// a new service goroutine for each. The service goroutines read requests
// and then call handler to reply to them
http.Serve(listener, nil)
}
func (t TimeServer) GiveServerTime(args Args, reply int64) error { // Set the value at the pointer got from the client reply = time.Now().Unix() return nil } Mutex-GPT package main
import ( "fmt" "sync" )
func add(a, b, c int, result chan<- int, wg sync.WaitGroup, m sync.Mutex) { defer wg.Done() // Notify the WaitGroup when this goroutine finishes
// Perform the addition
sum := a + b + c
// Lock the mutex before accessing the shared result channel
m.Lock()
defer m.Unlock() // Ensure the mutex is unlocked when the function exits
// Send the result to the channel
result <- sum
}
func main() { // Create a result channel result := make(chan int)
// Create a WaitGroup
var wg sync.WaitGroup
// Create a Mutex
var m sync.Mutex
// Add the number of goroutines to the WaitGroup
wg.Add(1)
// Launch the goroutine
go add(1, 2, 3, result, &wg, &m)
// Wait for the goroutine to finish
go func() {
wg.Wait()
// Close the result channel after all goroutines are done
close(result)
}()
// Receive the result from the channel
sum := <-result
fmt.Println("Sum:", sum)
} Mutex-banking package main
import ( "fmt" "sync" )
var ( mutex sync.Mutex balance int )
func init() { balance = 1000 }
func deposit(value int, wg *sync.WaitGroup) { mutex.Lock() fmt.Printf("Depositing %d to account with balance: %d\n", value, balance) balance += value mutex.Unlock() wg.Done() }
func withdraw(value int, wg *sync.WaitGroup) { mutex.Lock() fmt.Printf("Withdrawing %d from account with balance: %d\n", value, balance) balance -= value mutex.Unlock() wg.Done() }
func main() { fmt.Println("Go Mutex Example")
var wg sync.WaitGroup
wg.Add(2)
go withdraw(700, &wg)
go deposit(500, &wg)
wg.Wait()
fmt.Printf("New Balance %d\n", balance)
}