Last active
October 11, 2023 08:19
-
-
Save USA-RedDragon/bbd012659b3783c9a4a3ba49b6559499 to your computer and use it in GitHub Desktop.
Go Channels demo for a friend
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package ipsc | |
import ( | |
"fmt" | |
"net" | |
) | |
// Structs are sort of like classes | |
type UDP struct { | |
// Variable definitions are opposite to a lot of other languages | |
// in Go's case it's "pc is a net.PacketConn" vs other languages | |
// "we have a net.PacketConn named pc" | |
pc net.PacketConn | |
// the channel type, which can pass an array of bytes | |
write_chan chan []byte | |
} | |
// These New* function sort of function as | |
// constructors might in object oriented languages | |
func NewUDP() *UDP { | |
// The := operator makes a new variable without having | |
// to declare it. It also manages typing for you, like | |
// `auto` types in other languages | |
pc, err := net.ListenPacket("udp", ":31003") | |
// This is how error checking works in Go, no try-catch or exceptions | |
if err != nil { | |
panic(err) | |
} | |
// This just instantiates the struct above and returns the pointer to it | |
return &UDP{ | |
pc: pc, | |
// make is kinda what it says on the label, make a new channel that takes in bytes | |
// channels are one of a very few types that requires a pre-allocation with make() | |
write_chan: make(chan []byte), | |
} | |
} | |
// And these functions with (u *UDP) are declaring them | |
// a function of the struct so that later | |
// users can use this with udp.Start() where udp | |
// is a pointer to a UDP struct as defined above | |
func (u *UDP) Start() { | |
// String concatenation with a +!!! | |
fmt.Println("Listening on " + u.pc.LocalAddr().String()) | |
// the `go` keyword effectively spins up a coroutine | |
// stylized a "goroutine" because it's technically | |
// different and more lightweight. | |
// | |
// After the following two lines the start function will | |
// return and the reader (not shown here) and writer | |
// will be running | |
go u.reader() | |
go u.writer() | |
} | |
func (u *UDP) writer() { | |
// infinite loop so we keep the writer running | |
for { | |
// select is amazing, it is kinda like a switch-case | |
// but with channels it will block the thread until | |
// one of the conditions are met. This helps to avoid | |
// spinning on the cpu with a nasty infinite loop | |
select { | |
// this says create the data variable when data comes in from the write channel | |
// this is kinda like C++'s streams, but actually useful | |
case data := <-u.write_chan: | |
fmt.Printf("Writing %v\n", data) | |
// nifty little one-liner that also instantiates a UDPAddr pointer | |
_, err := u.pc.WriteTo(data, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 31000}) | |
if err != nil { | |
fmt.Println("Error sending packet: ", err) | |
continue | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment