-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add: channel impl, defer order, file TODO, decorator pattern, more sl…
…ices, int overflow
- Loading branch information
Petrus Breedt
committed
Sep 17, 2024
1 parent
62f940c
commit ddbe88d
Showing
13 changed files
with
289 additions
and
8 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package channels | ||
|
||
// Copyright 2010 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
// ###### | ||
// Codewalk through: https://go.dev/doc/codewalk/sharemem/ | ||
// Premise: Share Memory by Communicating | ||
|
||
import ( | ||
"log" | ||
"net/http" | ||
"time" | ||
) | ||
|
||
const ( | ||
numPollers = 2 // number of Poller goroutines to launch | ||
pollInterval = 60 * time.Second // how often to poll each URL | ||
statusInterval = 10 * time.Second // how often to log status to stdout | ||
errTimeout = 10 * time.Second // back-off timeout on error | ||
) | ||
|
||
var urls = []string{ | ||
"http://www.google.com/", | ||
"http://golang.org/", | ||
"http://blog.golang.org/", | ||
} | ||
|
||
// State represents the last-known state of a URL. | ||
type State struct { | ||
url string | ||
status string | ||
} | ||
|
||
// StateMonitor maintains a map that stores the state of the URLs being | ||
// polled, and prints the current state every updateInterval nanoseconds. | ||
// It returns a chan State to which resource state should be sent. | ||
func StateMonitor(updateInterval time.Duration) chan<- State { | ||
updates := make(chan State) | ||
urlStatus := make(map[string]string) | ||
ticker := time.NewTicker(updateInterval) | ||
go func() { | ||
for { | ||
select { | ||
case <-ticker.C: | ||
logState(urlStatus) | ||
case s := <-updates: | ||
urlStatus[s.url] = s.status | ||
} | ||
} | ||
}() | ||
return updates | ||
} | ||
|
||
// logState prints a state map. | ||
func logState(s map[string]string) { | ||
log.Println("Current state:") | ||
for k, v := range s { | ||
log.Printf(" %s %s", k, v) | ||
} | ||
} | ||
|
||
// Resource represents an HTTP URL to be polled by this program. | ||
type Resource struct { | ||
url string | ||
errCount int | ||
} | ||
|
||
// Poll executes an HTTP HEAD request for url | ||
// and returns the HTTP status string or an error string. | ||
func (r *Resource) Poll() string { | ||
resp, err := http.Head(r.url) | ||
if err != nil { | ||
log.Println("Error", r.url, err) | ||
r.errCount++ | ||
return err.Error() | ||
} | ||
r.errCount = 0 | ||
return resp.Status | ||
} | ||
|
||
// Sleep sleeps for an appropriate interval (dependent on error state) | ||
// before sending the Resource to done. | ||
func (r *Resource) Sleep(done chan<- *Resource) { | ||
time.Sleep(pollInterval + errTimeout*time.Duration(r.errCount)) | ||
done <- r | ||
} | ||
|
||
func Poller(in <-chan *Resource, out chan<- *Resource, status chan<- State) { | ||
for r := range in { | ||
s := r.Poll() | ||
status <- State{r.url, s} | ||
out <- r | ||
} | ||
} | ||
|
||
func main() { | ||
// Create our input and output channels. | ||
pending, complete := make(chan *Resource), make(chan *Resource) | ||
|
||
// Launch the StateMonitor. | ||
status := StateMonitor(statusInterval) | ||
|
||
// Launch some Poller goroutines. | ||
for i := 0; i < numPollers; i++ { | ||
go Poller(pending, complete, status) | ||
} | ||
|
||
// Send some Resources to the pending queue. | ||
go func() { | ||
for _, url := range urls { | ||
pending <- &Resource{url: url} | ||
} | ||
}() | ||
|
||
for r := range complete { | ||
go r.Sleep(pending) | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package dfer | ||
|
||
func basics() { | ||
order() | ||
} | ||
|
||
func order() { | ||
for i := 0; i < 5; i++ { | ||
// defers executed in LIFO order | ||
defer println(i) | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package dfer | ||
|
||
import "testing" | ||
|
||
func TestBasics(t *testing.T) { | ||
basics() | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package files | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
) | ||
|
||
func Read(filename string) ([]byte, int, error) { | ||
f, e := os.Open(filename) | ||
if e != nil { | ||
fmt.Printf("error opening file: %v", e) | ||
return nil, 0, e | ||
} | ||
|
||
b := make([]byte, 10) | ||
n, e := f.Read(b) | ||
return b, n, e | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package files | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestR(t *testing.T) { | ||
b, n, e := Read("test-file.txt") | ||
fmt.Printf("read %d bytes: %s (error=%v)", n, b, e) | ||
assert.Equal(t, nil, e) | ||
assert.Equal(t, []byte("abc\ndef\ngh"), b) | ||
assert.Equal(t, 10, n) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
abc | ||
def | ||
ghi | ||
jkl | ||
mno | ||
pqr | ||
stu | ||
vwx | ||
yz |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,11 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= | ||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package decorator | ||
|
||
import "fmt" | ||
|
||
type Reader interface { | ||
Read() string | ||
} | ||
|
||
type FileReader struct{} | ||
|
||
func (fr *FileReader) Read() string { | ||
return "Read file..." | ||
} | ||
|
||
type CompressReader struct { | ||
reader Reader | ||
} | ||
|
||
func (cr *CompressReader) Read() string { | ||
file := cr.reader.Read() | ||
return file + "Compress data..." | ||
} | ||
|
||
type EncryptReader struct { | ||
reader Reader | ||
} | ||
|
||
func (er *EncryptReader) Read() string { | ||
file := er.reader.Read() | ||
return file + "Encrypting data..." | ||
} | ||
|
||
func main() { | ||
fr := &FileReader{} | ||
cr := &CompressReader{fr} | ||
er := &EncryptReader{cr} | ||
|
||
fmt.Println(er.Read()) | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package decorator | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestReader(t *testing.T) { | ||
fr := &FileReader{} | ||
cr := &CompressReader{fr} | ||
er := &EncryptReader{cr} | ||
|
||
data := er.Read() | ||
expect := "Read file...Compress data...Encrypting data..." | ||
if data != expect { | ||
t.Fatalf("Fail: expected:%s, got:%s", expect, data) | ||
} | ||
} |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package types | ||
|
||
import "fmt" | ||
|
||
func overflow() int8 { | ||
var max int8 = 127 | ||
// overflow, results in -128 | ||
fmt.Println("int8: max=", max, ", max + 1=", max+1) | ||
return max + 1 | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package types | ||
|
||
import "testing" | ||
|
||
func TestOverflow(t *testing.T) { | ||
of := overflow() | ||
if of != -128 { | ||
t.Fail() | ||
} | ||
} |