This commit is contained in:
teivah 2021-12-27 15:56:17 +01:00
parent 8e2f2cb83d
commit b37e4abb2a
No known key found for this signature in database
GPG key ID: 07E4A13FB8F8DF63
154 changed files with 5466 additions and 1000362 deletions

View file

@ -0,0 +1,23 @@
package main
import "time"
func listing1() {
ticker := time.NewTicker(1000)
for {
select {
case <-ticker.C:
// Do something
}
}
}
func listing2() {
ticker := time.NewTicker(time.Microsecond)
for {
select {
case <-ticker.C:
// Do something
}
}
}

View file

@ -0,0 +1,51 @@
package main
import (
"context"
"log"
"time"
)
func consumer1(ch <-chan Event) {
for {
select {
case event := <-ch:
handle(event)
case <-time.After(time.Hour):
log.Println("warning: no messages received")
}
}
}
func consumer2(ch <-chan Event) {
for {
ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
select {
case event := <-ch:
cancel()
handle(event)
case <-ctx.Done():
log.Println("warning: no messages received")
}
}
}
func consumer3(ch <-chan Event) {
timerDuration := 1 * time.Hour
timer := time.NewTimer(timerDuration)
for {
timer.Reset(timerDuration)
select {
case event := <-ch:
handle(event)
case <-timer.C:
log.Println("warning: no messages received")
}
}
}
type Event struct{}
func handle(Event) {
}

View file

@ -0,0 +1,17 @@
package main
import "encoding/json"
func listing1() error {
b := getMessage()
var m map[string]any
err := json.Unmarshal(b, &m)
if err != nil {
return err
}
return nil
}
func getMessage() []byte {
return nil
}

View file

@ -0,0 +1,53 @@
package main
import (
"encoding/json"
"fmt"
"time"
)
type Event struct {
Time time.Time
}
func listing1() error {
t := time.Now()
event1 := Event{
Time: t,
}
b, err := json.Marshal(event1)
if err != nil {
return err
}
var event2 Event
err = json.Unmarshal(b, &event2)
if err != nil {
return err
}
fmt.Println(event1 == event2)
return nil
}
func listing2() error {
t := time.Now()
event1 := Event{
Time: t.Truncate(0),
}
b, err := json.Marshal(event1)
if err != nil {
return err
}
var event2 Event
err = json.Unmarshal(b, &event2)
if err != nil {
return err
}
fmt.Println(event1 == event2)
return nil
}

View file

@ -0,0 +1,56 @@
package main
import (
"encoding/json"
"fmt"
"time"
)
func main() {
if err := listing1(); err != nil {
panic(err)
}
if err := listing2(); err != nil {
panic(err)
}
}
type Event1 struct {
ID int
time.Time
}
func listing1() error {
event := Event1{
ID: 1234,
Time: time.Now(),
}
b, err := json.Marshal(event)
if err != nil {
return err
}
fmt.Println(string(b))
return nil
}
type Event2 struct {
ID int
Time time.Time
}
func listing2() error {
event := Event2{
ID: 1234,
Time: time.Now(),
}
b, err := json.Marshal(event)
if err != nil {
return err
}
fmt.Println(string(b))
return nil
}

View file

@ -0,0 +1,66 @@
package main
import "database/sql"
func listing1(db *sql.DB, id string) error {
rows, err := db.Query("SELECT DEP, AGE FROM EMP WHERE ID = ?", id)
if err != nil {
return err
}
// Defer closing rows
var (
department string
age int
)
for rows.Next() {
err := rows.Scan(&department, &age)
if err != nil {
return err
}
// ...
}
return nil
}
func listing2(db *sql.DB, id string) error {
rows, err := db.Query("SELECT DEP, AGE FROM EMP WHERE ID = ?", id)
if err != nil {
return err
}
// Defer closing rows
var (
department *string
age int
)
for rows.Next() {
err := rows.Scan(&department, &age)
if err != nil {
return err
}
// ...
}
return nil
}
func listing3(db *sql.DB, id string) error {
rows, err := db.Query("SELECT DEP, AGE FROM EMP WHERE ID = ?", id)
if err != nil {
return err
}
// Defer closing rows
var (
department sql.NullString
age int
)
for rows.Next() {
err := rows.Scan(&department, &age)
if err != nil {
return err
}
// ...
}
return nil
}

View file

@ -0,0 +1,16 @@
package main
import "database/sql"
func listing1(db *sql.DB, id string) error {
stmt, err := db.Prepare("SELECT * FROM ORDER WHERE ID = ?")
if err != nil {
return err
}
rows, err := stmt.Query(id)
if err != nil {
return err
}
_ = rows
return nil
}

View file

@ -0,0 +1,68 @@
package main
import (
"context"
"database/sql"
"log"
)
func (c *conn) get1(ctx context.Context, id string) (string, int, error) {
rows, err := c.db.QueryContext(ctx,
"SELECT DEP, AGE FROM EMP WHERE ID = ?", id)
if err != nil {
return "", 0, err
}
defer func() {
err := rows.Close()
if err != nil {
log.Printf("failed to close rows: %v\n", err)
}
}()
var (
department string
age int
)
for rows.Next() {
err := rows.Scan(&department, &age)
if err != nil {
return "", 0, err
}
}
return department, age, nil
}
func (c *conn) get2(ctx context.Context, id string) (string, int, error) {
rows, err := c.db.QueryContext(ctx,
"SELECT DEP, AGE FROM EMP WHERE ID = ?", id)
if err != nil {
return "", 0, err
}
defer func() {
err := rows.Close()
if err != nil {
log.Printf("failed to close rows: %v\n", err)
}
}()
var (
department string
age int
)
for rows.Next() {
err := rows.Scan(&department, &age)
if err != nil {
return "", 0, err
}
}
if err := rows.Err(); err != nil {
return "", 0, err
}
return department, age, nil
}
type conn struct {
db *sql.DB
}

View file

@ -0,0 +1,19 @@
package main
import "database/sql"
var dsn = ""
func listing1() error {
db, err := sql.Open("mysql", dsn)
if err != nil {
return err
}
if err := db.Ping(); err != nil {
return err
}
_ = db
return nil
}

View file

@ -0,0 +1,81 @@
package main
import (
"io"
"log"
"net/http"
)
func (h handler) getBody1() (string, error) {
resp, err := h.client.Get(h.url)
if err != nil {
return "", err
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
func (h handler) getBody2() (string, error) {
resp, err := h.client.Get(h.url)
if err != nil {
return "", err
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
defer func() {
err := resp.Body.Close()
if err != nil {
log.Printf("failed to close response: %v\n", err)
}
}()
return string(body), nil
}
func (h handler) getStatusCode1(body io.Reader) (int, error) {
resp, err := h.client.Post(h.url, "application/json", body)
if err != nil {
return 0, err
}
defer func() {
err := resp.Body.Close()
if err != nil {
log.Printf("failed to close response: %v\n", err)
}
}()
return resp.StatusCode, nil
}
func (h handler) getStatusCode2(body io.Reader) (int, error) {
resp, err := h.client.Post(h.url, "application/json", body)
if err != nil {
return 0, err
}
defer func() {
err := resp.Body.Close()
if err != nil {
log.Printf("failed to close response: %v\n", err)
}
}()
_, _ = io.Copy(io.Discard, resp.Body)
return resp.StatusCode, nil
}
type handler struct {
client http.Client
url string
}

View file

@ -0,0 +1,56 @@
package main
import (
"log"
"os"
)
func listing1(filename string) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
return err
}
defer func() {
if err := f.Close(); err != nil {
log.Printf("failed to close file: %v\n", err)
}
}()
return nil
}
func writeToFile1(filename string, content []byte) (err error) {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
return err
}
defer func() {
closeErr := f.Close()
if err == nil {
err = closeErr
}
}()
_, err = f.Write(content)
return
}
func writeToFile2(filename string, content []byte) (err error) {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
if err != nil {
return err
}
defer func() {
_ = f.Close()
}()
_, err = f.Write(content)
if err != nil {
return err
}
return f.Sync()
}

View file

@ -0,0 +1,48 @@
package main
import (
"database/sql"
"log"
)
func listing1() error {
db, err := sql.Open("postgres", dataSourceName)
if err != nil {
return err
}
rows, err := db.Query("SELECT * FROM CUSTOMERS")
if err != nil {
return err
}
// Use rows
_ = rows
return nil
}
func listing2() error {
db, err := sql.Open("postgres", dataSourceName)
if err != nil {
return err
}
rows, err := db.Query("SELECT * FROM CUSTOMERS")
if err != nil {
return err
}
defer func() {
if err := rows.Close(); err != nil {
log.Printf("failed to close rows: %v\n", err)
}
}()
// Use rows
_ = rows
return nil
}
var dataSourceName = ""

View file

@ -0,0 +1,28 @@
package main
import "net/http"
func handler1(w http.ResponseWriter, req *http.Request) {
err := foo(req)
if err != nil {
http.Error(w, "foo", http.StatusInternalServerError)
}
_, _ = w.Write([]byte("all good"))
w.WriteHeader(http.StatusCreated)
}
func handler2(w http.ResponseWriter, req *http.Request) {
err := foo(req)
if err != nil {
http.Error(w, "foo", http.StatusInternalServerError)
return
}
_, _ = w.Write([]byte("all good"))
w.WriteHeader(http.StatusCreated)
}
func foo(req *http.Request) error {
return nil
}

View file

@ -0,0 +1,21 @@
package main
import (
"net"
"net/http"
"time"
)
func main() {
client := &http.Client{
Timeout: 5 * time.Second,
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: time.Second,
}).DialContext,
TLSHandshakeTimeout: time.Second,
ResponseHeaderTimeout: time.Second,
},
}
_ = client
}

View file

@ -0,0 +1,20 @@
package main
import (
"net/http"
"time"
)
func main() {
s := &http.Server{
Addr: ":8080",
ReadHeaderTimeout: 500 * time.Millisecond,
ReadTimeout: 500 * time.Millisecond,
Handler: http.TimeoutHandler(handler{}, time.Second, "foo"),
}
_ = s
}
type handler struct{}
func (h handler) ServeHTTP(http.ResponseWriter, *http.Request) {}

View file

@ -0,0 +1,19 @@
// +build integration
package db
import (
"testing"
)
func TestInsert1(t *testing.T) {
// ...
}
func TestInsert2(t *testing.T) {
if os.Getenv("INTEGRATION") != "true" {
t.Skip("skipping integration test")
}
// ...
}

View file

@ -0,0 +1,10 @@
package main
import "testing"
func TestLongRunning(t *testing.T) {
if testing.Short() {
t.Skip("skipping long-running test")
}
// ...
}

View file

@ -0,0 +1,16 @@
package main
import "strings"
func removeNewLineSuffixes(s string) string {
if s == "" {
return s
}
if strings.HasSuffix(s, "\r\n") {
return removeNewLineSuffixes(s[:len(s)-2])
}
if strings.HasSuffix(s, "\n") {
return removeNewLineSuffixes(s[:len(s)-1])
}
return s
}

View file

@ -0,0 +1,81 @@
package main
import "testing"
func TestRemoveNewLineSuffix_Empty(t *testing.T) {
got := removeNewLineSuffixes("")
expected := ""
if got != expected {
t.Errorf("got: %s", got)
}
}
func TestRemoveNewLineSuffix_EndingWithCarriageReturnNewLine(t *testing.T) {
got := removeNewLineSuffixes("a\r\n")
expected := "a"
if got != expected {
t.Errorf("got: %s", got)
}
}
func TestRemoveNewLineSuffix_EndingWithNewLine(t *testing.T) {
got := removeNewLineSuffixes("a\n")
expected := "a"
if got != expected {
t.Errorf("got: %s", got)
}
}
func TestRemoveNewLineSuffix_EndingWithMultipleNewLines(t *testing.T) {
got := removeNewLineSuffixes("a\n\n\n")
expected := "a"
if got != expected {
t.Errorf("got: %s", got)
}
}
func TestRemoveNewLineSuffix_EndingWithoutNewLine(t *testing.T) {
got := removeNewLineSuffixes("a\n")
expected := "a"
if got != expected {
t.Errorf("got: %s", got)
}
}
func TestRemoveNewLineSuffix(t *testing.T) {
tests := map[string]struct {
input string
expected string
}{
`empty`: {
input: "",
expected: "",
},
`ending with \r\n`: {
input: "a\r\n",
expected: "a",
},
`ending with \n`: {
input: "a\n",
expected: "a",
},
`ending with multiple \n`: {
input: "a\n\n\n",
expected: "a",
},
`ending without newline`: {
input: "a",
expected: "a",
},
}
for name, tt := range tests {
tt := tt
t.Run(name, func(t *testing.T) {
t.Parallel()
got := removeNewLineSuffixes(tt.input)
if got != tt.expected {
t.Errorf("got: %s, expected: %s", got, tt.expected)
}
})
}
}

View file

@ -0,0 +1,30 @@
package main
type Handler struct {
n int
publisher publisher
}
type publisher interface {
Publish([]Foo)
}
func (h Handler) getBestFoo(someInputs int) Foo {
foos := getFoos(someInputs)
best := foos[0]
go func() {
if len(foos) > h.n {
foos = foos[:h.n]
}
h.publisher.Publish(foos)
}()
return best
}
func getFoos(inputs int) []Foo {
return make([]Foo, 100)
}
type Foo struct{}

View file

@ -0,0 +1,79 @@
package main
import (
"sync"
"testing"
"time"
)
type publisherMock1 struct {
mu sync.RWMutex
got []Foo
}
func (p *publisherMock1) Publish(got []Foo) {
p.mu.Lock()
defer p.mu.Unlock()
p.got = got
}
func (p *publisherMock1) Get() []Foo {
p.mu.RLock()
defer p.mu.RUnlock()
return p.got
}
func TestGetBestFoo(t *testing.T) {
mock := publisherMock1{}
h := Handler{
publisher: &mock,
n: 2,
}
foo := h.getBestFoo(42)
// Check foo
_ = foo
time.Sleep(10 * time.Millisecond)
published := mock.Get()
// Check published
_ = published
}
func assert(t *testing.T, assertion func() bool,
maxRetry int, waitTime time.Duration) {
for i := 0; i < maxRetry; i++ {
if assertion() {
return
}
time.Sleep(waitTime)
}
t.Fail()
}
type publisherMock2 struct {
ch chan []Foo
}
func (p *publisherMock2) Publish(got []Foo) {
p.ch <- got
}
func TestGetBestFoo2(t *testing.T) {
mock := publisherMock2{
ch: make(chan []Foo),
}
defer close(mock.ch)
h := Handler{
publisher: &mock,
n: 2,
}
foo := h.getBestFoo(42)
// Check foo
_ = foo
if v := len(<-mock.ch); v != 2 {
t.Fatalf("expected 2, got %d", v)
}
}

View file

@ -0,0 +1,43 @@
package listing1
import (
"sync"
"time"
)
type Cache struct {
mu sync.RWMutex
events []Event
}
type Event struct {
Timestamp time.Time
Data string
}
func (c *Cache) TrimBefore(since time.Duration) {
c.mu.RLock()
defer c.mu.RUnlock()
t := time.Now().Add(-since)
for i := 0; i < len(c.events); i++ {
if c.events[i].Timestamp.After(t) {
c.events = c.events[i:]
return
}
}
}
func (c *Cache) Add(events []Event) {
c.mu.Lock()
defer c.mu.Unlock()
c.events = append(c.events, events...)
}
func (c *Cache) GetAll() []Event {
c.mu.RLock()
defer c.mu.RUnlock()
return c.events
}

View file

@ -0,0 +1,22 @@
package listing1
import (
"testing"
"time"
)
func TestCache_TrimBefore(t *testing.T) {
events := []Event{
{Timestamp: time.Now().Add(-20 * time.Millisecond)},
{Timestamp: time.Now().Add(-10 * time.Millisecond)},
{Timestamp: time.Now().Add(10 * time.Millisecond)},
}
cache := &Cache{}
cache.Add(events)
cache.TrimBefore(15 * time.Millisecond)
got := cache.GetAll()
expected := 2
if len(got) != expected {
t.Fatalf("expected %d, got %d", expected, len(got))
}
}

View file

@ -0,0 +1,53 @@
package listing1
import (
"sync"
"time"
)
type now func() time.Time
type Cache struct {
mu sync.RWMutex
events []Event
now now
}
func NewCache() *Cache {
return &Cache{
events: make([]Event, 0),
now: time.Now,
}
}
type Event struct {
Timestamp time.Time
Data string
}
func (c *Cache) TrimBefore(since time.Duration) {
c.mu.RLock()
defer c.mu.RUnlock()
t := time.Now().Add(-since)
for i := 0; i < len(c.events); i++ {
if c.events[i].Timestamp.After(t) {
c.events = c.events[i:]
return
}
}
}
func (c *Cache) Add(events []Event) {
c.mu.Lock()
defer c.mu.Unlock()
c.events = append(c.events, events...)
}
func (c *Cache) GetAll() []Event {
c.mu.RLock()
defer c.mu.RUnlock()
return c.events
}

View file

@ -0,0 +1,28 @@
package listing1
import (
"testing"
"time"
)
func TestCache_TrimBefore(t *testing.T) {
events := []Event{
{Timestamp: parseTime(t, "2020-01-01T12:00:00.04Z")},
{Timestamp: parseTime(t, "2020-01-01T12:00:00.05Z")},
{Timestamp: parseTime(t, "2020-01-01T12:00:00.06Z")},
}
cache := &Cache{now: func() time.Time {
return parseTime(t, "2020-01-01T12:00:00.06Z")
}}
cache.Add(events)
cache.TrimBefore(15 * time.Millisecond)
// ...
}
func parseTime(t *testing.T, timestamp string) time.Time {
ts, err := time.Parse(time.RFC3339, timestamp)
if err != nil {
t.FailNow()
}
return ts
}

View file

@ -0,0 +1,43 @@
package listing1
import (
"sync"
"time"
)
type Cache struct {
mu sync.RWMutex
events []Event
}
type Event struct {
Timestamp time.Time
Data string
}
func (c *Cache) TrimBefore(now time.Time, since time.Duration) {
c.mu.RLock()
defer c.mu.RUnlock()
t := now.Add(-since)
for i := 0; i < len(c.events); i++ {
if c.events[i].Timestamp.After(t) {
c.events = c.events[i:]
return
}
}
}
func (c *Cache) Add(events []Event) {
c.mu.Lock()
defer c.mu.Unlock()
c.events = append(c.events, events...)
}
func (c *Cache) GetAll() []Event {
c.mu.RLock()
defer c.mu.RUnlock()
return c.events
}

View file

@ -0,0 +1,30 @@
package listing1
import (
"testing"
"time"
)
func TestCache_TrimBefore(t *testing.T) {
events := []Event{
{Timestamp: time.Now().Add(-20 * time.Millisecond)},
{Timestamp: time.Now().Add(-10 * time.Millisecond)},
{Timestamp: time.Now().Add(10 * time.Millisecond)},
}
cache := &Cache{}
cache.Add(events)
cache.TrimBefore(parseTime(t, "2020-01-01T12:00:00.06Z"), 15*time.Millisecond)
got := cache.GetAll()
expected := 2
if len(got) != expected {
t.Fatalf("expected %d, got %d", expected, len(got))
}
}
func parseTime(t *testing.T, timestamp string) time.Time {
ts, err := time.Parse(time.RFC3339, timestamp)
if err != nil {
t.FailNow()
}
return ts
}

View file

@ -0,0 +1,65 @@
package main
import (
"encoding/json"
"io"
"net/http"
"strings"
"time"
)
func Handler(w http.ResponseWriter, r *http.Request) {
w.Header().Add("X-API-VERSION", "1.0")
b, _ := io.ReadAll(r.Body)
_, _ = w.Write(append([]byte("hello "), b...))
w.WriteHeader(http.StatusCreated)
}
func (c DurationClient) GetDuration(url string,
lat1, lng1, lat2, lng2 float64) (
time.Duration, error) {
resp, err := c.client.Post(
url, "application/json",
buildRequestBody(lat1, lng1, lat2, lng2),
)
if err != nil {
return 0, err
}
return parseResponseBody(resp.Body)
}
type request struct {
Duration int
}
func buildRequestBody(lat1, lng1, lat2, lng2 float64) io.Reader {
return strings.NewReader("")
}
type DurationClient struct {
client *http.Client
}
func NewDurationClient() DurationClient {
return DurationClient{
client: http.DefaultClient,
}
}
func parseResponseBody(r io.ReadCloser) (time.Duration, error) {
b, err := io.ReadAll(r)
if err != nil {
return 0, err
}
defer func() {
_ = r.Close()
}()
var req request
err = json.Unmarshal(b, &req)
if err != nil {
return 0, err
}
return time.Duration(req.Duration) * time.Second, nil
}

View file

@ -0,0 +1,52 @@
package main
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
func TestHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost",
strings.NewReader("foo"))
w := httptest.NewRecorder()
Handler(w, req)
if got := w.Result().Header.Get("X-API-VERSION"); got != "1.0" {
t.Errorf("api version: expected 1.0, got %s", got)
}
body, _ := ioutil.ReadAll(w.Body)
if got := string(body); got != "hello foo" {
t.Errorf("body: expected hello foo, got %s", got)
}
if http.StatusOK != w.Result().StatusCode {
t.FailNow()
}
}
func TestDurationClientGet(t *testing.T) {
srv := httptest.NewServer(
http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"duration": 314}`))
},
),
)
defer srv.Close()
client := NewDurationClient()
duration, err :=
client.GetDuration(srv.URL, 51.551261, -0.1221146, 51.57, -0.13)
if err != nil {
t.Fatal(err)
}
if duration != 314*time.Second {
t.Errorf("expected 314 seconds, got %v", duration)
}
}

View file

@ -0,0 +1,44 @@
package main
import (
"io"
)
type LowerCaseReader struct {
reader io.Reader
}
func (l LowerCaseReader) Read(p []byte) (int, error) {
return 0, nil
}
func foo(r io.Reader) error {
b, err := io.ReadAll(r)
if err != nil {
return err
}
// ...
_ = b
return nil
}
func readAll(r io.Reader, retries int) ([]byte, error) {
b := make([]byte, 0, 512)
for {
if len(b) == cap(b) {
b = append(b, 0)[:len(b)]
}
n, err := r.Read(b[len(b):cap(b)])
b = b[:len(b)+n]
if err != nil {
if err == io.EOF {
err = nil
}
retries--
if retries <= 0 {
return b, err
}
}
}
}

View file

@ -0,0 +1,30 @@
package main
import (
"strings"
"testing"
"testing/iotest"
)
func TestLowerCaseReader(t *testing.T) {
err := iotest.TestReader(
&LowerCaseReader{reader: strings.NewReader("aBcDeFgHiJ")},
[]byte("acegi"),
)
if err != nil {
t.Fatal(err)
}
}
func TestFoo(t *testing.T) {
err := foo(iotest.TimeoutReader(
strings.NewReader(randomString(1024)),
))
if err != nil {
t.Fatal(err)
}
}
func randomString(i int) string {
return string(make([]byte, i))
}

View file

@ -0,0 +1,15 @@
package main
const (
m1 = 0x5555555555555555
m2 = 0x3333333333333333
m4 = 0x0f0f0f0f0f0f0f0f
h01 = 0x0101010101010101
)
func popcnt(x uint64) uint64 {
x -= (x >> 1) & m1
x = (x & m2) + ((x >> 2) & m2)
x = (x + (x >> 4)) & m4
return (x * h01) >> 56
}

View file

@ -0,0 +1,19 @@
package main
import "testing"
func BenchmarkPopcnt1(b *testing.B) {
for i := 0; i < b.N; i++ {
popcnt(uint64(i))
}
}
var global uint64
func BenchmarkPopcnt2(b *testing.B) {
var v uint64
for i := 0; i < b.N; i++ {
v = popcnt(uint64(i))
}
global = v
}

View file

@ -0,0 +1,21 @@
package main
func calculateSum512(s [][512]int64) int64 {
var sum int64
for i := 0; i < len(s); i++ {
for j := 0; j < 8; j++ {
sum += s[i][j]
}
}
return sum
}
func calculateSum513(s [][513]int64) int64 {
var sum int64
for i := 0; i < len(s); i++ {
for j := 0; j < 8; j++ {
sum += s[i][j]
}
}
return sum
}

View file

@ -0,0 +1,57 @@
package main
import "testing"
const rows = 1000
var res int64
func BenchmarkCalculateSum512_1(b *testing.B) {
var sum int64
s := createMatrix512(rows)
b.ResetTimer()
for i := 0; i < b.N; i++ {
sum = calculateSum512(s)
}
res = sum
}
func BenchmarkCalculateSum513_1(b *testing.B) {
var sum int64
s := createMatrix513(rows)
b.ResetTimer()
for i := 0; i < b.N; i++ {
sum = calculateSum513(s)
}
res = sum
}
func BenchmarkCalculateSum512_2(b *testing.B) {
var sum int64
for i := 0; i < b.N; i++ {
b.StopTimer()
s := createMatrix512(rows)
b.StartTimer()
sum = calculateSum512(s)
}
res = sum
}
func BenchmarkCalculateSum513_2(b *testing.B) {
var sum int64
for i := 0; i < b.N; i++ {
b.StopTimer()
s := createMatrix512(rows)
b.StartTimer()
sum = calculateSum512(s)
}
res = sum
}
func createMatrix512(r int) [][512]int64 {
return make([][512]int64, r)
}
func createMatrix513(r int) [][513]int64 {
return make([][513]int64, r)
}

View file

@ -0,0 +1,26 @@
package timer
import "testing"
func BenchmarkFoo1(b *testing.B) {
expensiveSetup()
b.ResetTimer()
for i := 0; i < b.N; i++ {
functionUnderTest()
}
}
func BenchmarkFoo2(b *testing.B) {
for i := 0; i < b.N; i++ {
b.StopTimer()
expensiveSetup()
b.StartTimer()
functionUnderTest()
}
}
func functionUnderTest() {
}
func expensiveSetup() {
}

View file

@ -0,0 +1,20 @@
package main
import (
"sync/atomic"
"testing"
)
func BenchmarkAtomicStoreInt32(b *testing.B) {
var v int32
for i := 0; i < b.N; i++ {
atomic.StoreInt32(&v, 1)
}
}
func BenchmarkAtomicStoreInt64(b *testing.B) {
var v int64
for i := 0; i < b.N; i++ {
atomic.StoreInt64(&v, 1)
}
}

View file

@ -0,0 +1,10 @@
package counter
import "sync/atomic"
var count uint64
func Inc() uint64 {
atomic.AddUint64(&count, 1)
return count
}

View file

@ -0,0 +1,13 @@
package counter_test
import (
"testing"
counter "github.com/teivah/100-go-mistakes/11-testing/90-testing-features/different-package"
)
func TestCount(t *testing.T) {
if counter.Inc() != 1 {
t.Errorf("expected 1")
}
}

View file

@ -0,0 +1,37 @@
package main
import (
"database/sql"
"os"
"testing"
)
func TestMySQLIntegration(t *testing.T) {
s := setupMySQL()
defer teardownMySQL(s)
// ...
}
func createConnection(t *testing.T, dsn string) *sql.DB {
db, err := sql.Open("mysql", dsn)
if err != nil {
t.FailNow()
}
t.Cleanup(
func() {
_ = db.Close()
})
return db
}
func TestMain(m *testing.M) {
s := setupMySQL()
code := m.Run()
teardownMySQL(s)
os.Exit(code)
}
func setupMySQL() interface{} { return nil }
func teardownMySQL(m interface{}) {}

View file

@ -0,0 +1,22 @@
package main
func NewStore() Store {
return Store{}
}
type Store struct{}
func (s Store) PutCustomer(Customer) error {
return nil
}
type Customer struct {
id string
}
func customerFactory(id string) (Customer, error) {
if id == "" {
return Customer{}, nil
}
return Customer{id: id}, nil
}

View file

@ -0,0 +1,36 @@
package main
import "testing"
func TestPutCustomer1(t *testing.T) {
customer, err := createCustomer1()
if err != nil {
t.Fatal(err)
}
err = NewStore().PutCustomer(customer)
// Check err
_ = err
}
func createCustomer1() (Customer, error) {
customer, err := customerFactory("foo")
if err != nil {
return Customer{}, nil
}
return customer, nil
}
func TestPutCustomer(t *testing.T) {
customer := createCustomer2(t)
err := NewStore().PutCustomer(customer)
// Check err
_ = err
}
func createCustomer2(t *testing.T) Customer {
customer, err := customerFactory("foo")
if err != nil {
t.Fatal(err)
}
return customer
}

View file

@ -0,0 +1,17 @@
package main
func sum2(s []int64) int64 {
var total int64
for i := 0; i < len(s); i += 2 {
total += s[i]
}
return total
}
func sum8(s []int64) int64 {
var total int64
for i := 0; i < len(s); i += 8 {
total += s[i]
}
return total
}

View file

@ -0,0 +1,27 @@
package main
import "testing"
var global int64
func BenchmarkSum2(b *testing.B) {
var local int64
for i := 0; i < b.N; i++ {
b.StopTimer()
s := make([]int64, 1_000_000)
b.StartTimer()
local = sum2(s)
}
global = local
}
func BenchmarkSum8(b *testing.B) {
var local int64
for i := 0; i < b.N; i++ {
b.StopTimer()
s := make([]int64, 1_000_000)
b.StartTimer()
local = sum8(s)
}
global = local
}

View file

@ -0,0 +1,23 @@
package main
type node struct {
value int64
next *node
}
func linkedList(n *node) int64 {
var total int64
for n != nil {
total += n.value
n = n.next
}
return total
}
func sum2(s []int64) int64 {
var total int64
for i := 0; i < len(s); i += 2 {
total += s[i]
}
return total
}

View file

@ -0,0 +1,27 @@
package main
type Foo struct {
a int64
b int64
}
func sumFoo(foos []Foo) int64 {
var total int64
for i := 0; i < len(foos); i++ {
total += foos[i].a
}
return total
}
type Bar struct {
a []int64
b []int64
}
func sumBar(bar Bar) int64 {
var total int64
for i := 0; i < len(bar.a); i++ {
total += bar.a[i]
}
return total
}

View file

@ -0,0 +1,32 @@
package main
import "testing"
var global int64
const n = 1_000_000
func BenchmarkSumFoo(b *testing.B) {
var local int64
for i := 0; i < b.N; i++ {
b.StopTimer()
s := make([]Foo, n)
b.StartTimer()
local = sumFoo(s)
}
global = local
}
func BenchmarkSumBar(b *testing.B) {
var local int64
for i := 0; i < b.N; i++ {
b.StopTimer()
bar := Bar{
a: make([]int64, n),
b: make([]int64, n),
}
b.StartTimer()
local = sumBar(bar)
}
global = local
}

View file

@ -0,0 +1,67 @@
package main
import "sync"
type Input struct {
a int64
b int64
}
type Result1 struct {
sumA int64
sumB int64
}
func count1(inputs []Input) Result1 {
wg := sync.WaitGroup{}
wg.Add(2)
result := Result1{}
go func() {
for i := 0; i < len(inputs); i++ {
result.sumA += inputs[i].a
}
wg.Done()
}()
go func() {
for i := 0; i < len(inputs); i++ {
result.sumB += inputs[i].b
}
wg.Done()
}()
wg.Wait()
return result
}
type Result2 struct {
sumA int64
_ [56]byte
sumB int64
}
func count2(inputs []Input) Result2 {
wg := sync.WaitGroup{}
wg.Add(2)
result := Result2{}
go func() {
for i := 0; i < len(inputs); i++ {
result.sumA += inputs[i].a
}
wg.Done()
}()
go func() {
for i := 0; i < len(inputs); i++ {
result.sumB += inputs[i].b
}
wg.Done()
}()
wg.Wait()
return result
}

View file

@ -0,0 +1,31 @@
package main
import "testing"
const n = 1_000_000
var globalResult1 Result1
func BenchmarkCount1(b *testing.B) {
var local Result1
for i := 0; i < b.N; i++ {
b.StopTimer()
inputs := make([]Input, n)
b.StartTimer()
local = count1(inputs)
}
globalResult1 = local
}
var globalResult2 Result2
func BenchmarkCount2(b *testing.B) {
var local Result2
for i := 0; i < b.N; i++ {
b.StopTimer()
inputs := make([]Input, n)
b.StartTimer()
local = count2(inputs)
}
globalResult2 = local
}

View file

@ -0,0 +1,24 @@
package main
const n = 1_000_000
func add(s [2]int64) [2]int64 {
for i := 0; i < n; i++ {
s[0]++
if s[0]%2 == 0 {
s[1]++
}
}
return s
}
func add2(s [2]int64) [2]int64 {
for i := 0; i < n; i++ {
v := s[0]
s[0] = v + 1
if v%2 != 0 {
s[1]++
}
}
return s
}

View file

@ -0,0 +1,23 @@
package main
import "testing"
var global [2]int64
func BenchmarkAdd(b *testing.B) {
a := [2]int64{}
var local [2]int64
for i := 0; i < b.N; i++ {
local = add(a)
}
global = local
}
func BenchmarkAdd2(b *testing.B) {
a := [2]int64{}
var local [2]int64
for i := 0; i < b.N; i++ {
local = add2(a)
}
global = local
}

View file

@ -0,0 +1,29 @@
package main
type Foo1 struct {
b1 byte
i int64
b2 byte
}
func sum1(foos []Foo1) int64 {
var s int64
for i := 0; i < len(foos); i++ {
s += foos[i].i
}
return s
}
type Foo2 struct {
i int64
b1 byte
b2 byte
}
func sum2(foos []Foo2) int64 {
var s int64
for i := 0; i < len(foos); i++ {
s += foos[i].i
}
return s
}

View file

@ -0,0 +1,27 @@
package main
import "testing"
const n = 1_000_000
var global int64
func BenchmarkSum1(b *testing.B) {
var local int64
s := make([]Foo1, n)
b.ResetTimer()
for i := 0; i < b.N; i++ {
local = sum1(s)
}
global = local
}
func BenchmarkSum2(b *testing.B) {
var local int64
s := make([]Foo2, n)
b.ResetTimer()
for i := 0; i < b.N; i++ {
local = sum2(s)
}
global = local
}

View file

@ -0,0 +1,41 @@
package main
func listing1() {
a := 3
b := 2
c := sumValue(a, b)
println(c)
}
//go:noinline
func sumValue(x, y int) int {
z := x + y
return z
}
func listing2() {
a := 3
b := 2
c := sumPtr(a, b)
println(*c)
}
//go:noinline
func sumPtr(x, y int) *int {
z := x + y
return &z
}
func listing3() {
a := 3
b := 2
c := sum(&a, &b)
println(c)
}
//go:noinline
func sum(x, y *int) int {
return *x + *y
}

View file

@ -0,0 +1,26 @@
package main
import "testing"
var (
globalValue int
globalPtr *int
)
func BenchmarkSumValue(b *testing.B) {
b.ReportAllocs()
var local int
for i := 0; i < b.N; i++ {
local = sumValue(i, i)
}
globalValue = local
}
func BenchmarkSumPtr(b *testing.B) {
b.ReportAllocs()
var local *int
for i := 0; i < b.N; i++ {
local = sumPtr(i, i)
}
globalValue = *local
}

View file

@ -0,0 +1,16 @@
package main
type cache struct {
m map[string]int
}
func (c *cache) get1(bytes []byte) (v int, contains bool) {
key := string(bytes)
v, contains = c.m[key]
return
}
func (c *cache) get2(bytes []byte) (v int, contains bool) {
v, contains = c.m[string(bytes)]
return
}

View file

@ -0,0 +1,24 @@
package main
import (
"io"
"sync"
)
var pool = sync.Pool{
New: func() any {
return make([]byte, 1024)
},
}
func write(w io.Writer) {
buffer := pool.Get().([]byte)
buffer = buffer[:0]
defer pool.Put(buffer)
getResponse(buffer)
_, _ = w.Write(buffer)
}
func getResponse([]byte) {
}

View file

@ -0,0 +1,75 @@
package main
import (
"log"
"net/http"
)
func listing1() error {
var client *http.Client
if tracing {
client, err := createClientWithTracing()
if err != nil {
return err
}
log.Println(client)
} else {
client, err := createDefaultClient()
if err != nil {
return err
}
log.Println(client)
}
_ = client
return nil
}
func listing2() error {
var client *http.Client
if tracing {
c, err := createClientWithTracing()
if err != nil {
return err
}
client = c
} else {
c, err := createDefaultClient()
if err != nil {
return err
}
client = c
}
_ = client
return nil
}
func listing3() error {
var client *http.Client
var err error
if tracing {
client, err = createClientWithTracing()
if err != nil {
return err
}
} else {
client, err = createDefaultClient()
if err != nil {
return err
}
}
_ = client
return nil
}
var tracing bool
func createClientWithTracing() (*http.Client, error) {
return nil, nil
}
func createDefaultClient() (*http.Client, error) {
return nil, nil
}

View file

@ -0,0 +1,54 @@
package main
import (
"io"
"os"
"sync"
)
type Foo struct {
Bar
}
type Bar struct {
Baz int
}
func fooBar() {
foo := Foo{}
foo.Baz = 42
}
type InMem struct {
sync.Mutex
m map[string]int
}
func New() *InMem {
return &InMem{m: make(map[string]int)}
}
func (i *InMem) Get(key string) (int, bool) {
i.Lock()
v, contains := i.m[key]
i.Unlock()
return v, contains
}
type Logger struct {
writeCloser io.WriteCloser
}
func (l Logger) Write(p []byte) (int, error) {
return l.writeCloser.Write(p)
}
func (l Logger) Close() error {
return l.writeCloser.Close()
}
func main() {
l := Logger{writeCloser: os.Stdout}
_, _ = l.Write([]byte("foo"))
_ = l.Close()
}

View file

@ -0,0 +1,64 @@
package main
import (
"errors"
"net/http"
)
const defaultHTTPPort = 8080
type Config struct {
Port int
}
type ConfigBuilder struct {
port *int
}
func (b *ConfigBuilder) Port(port int) *ConfigBuilder {
b.port = &port
return b
}
func (b *ConfigBuilder) Build() (Config, error) {
cfg := Config{}
if b.port == nil {
cfg.Port = defaultHTTPPort
} else {
if *b.port == 0 {
cfg.Port = randomPort()
} else if *b.port < 0 {
return Config{}, errors.New("port should be positive")
} else {
cfg.Port = *b.port
}
}
return cfg, nil
}
func NewServer(addr string, config Config) (*http.Server, error) {
return nil, nil
}
func client() error {
builder := ConfigBuilder{}
builder.Port(8080)
cfg, err := builder.Build()
if err != nil {
return err
}
server, err := NewServer("localhost", cfg)
if err != nil {
return err
}
_ = server
return nil
}
func randomPort() int {
return 4 // Chosen by fair dice roll, guaranteed to be random.
}

View file

@ -0,0 +1,12 @@
package main
type Config struct {
Port int
}
func NewServer(addr string, cfg Config) {
}
func main() {
NewServer("localhost", Config{})
}

View file

@ -0,0 +1,58 @@
package main
import (
"errors"
"net/http"
)
const defaultHTTPPort = 8080
type options struct {
port *int
}
type Option func(options *options) error
func WithPort(port int) Option {
return func(options *options) error {
if port < 0 {
return errors.New("port should be positive")
}
options.port = &port
return nil
}
}
func NewServer(addr string, opts ...Option) (*http.Server, error) {
var options options
for _, opt := range opts {
err := opt(&options)
if err != nil {
return nil, err
}
}
// At this stage, the options struct is built and contains the config
// Therefore, we can implement our logic related to port configuration
var port int
if options.port == nil {
port = defaultHTTPPort
} else {
if *options.port == 0 {
port = randomPort()
} else {
port = *options.port
}
}
_ = port
return nil, nil
}
func client() {
_, _ = NewServer("localhost", WithPort(8080))
}
func randomPort() int {
return 4 // Chosen by fair dice roll, guaranteed to be random.
}

View file

@ -0,0 +1,7 @@
package stringset
type Set map[string]struct{}
func New(...string) Set { return nil }
func (s Set) Sort() []string { return nil }

View file

@ -0,0 +1,45 @@
package main
import "errors"
func join1(s1, s2 string, max int) (string, error) {
if s1 == "" {
return "", errors.New("s1 is empty")
} else {
if s2 == "" {
return "", errors.New("s2 is empty")
} else {
concat, err := concatenate(s1, s2)
if err != nil {
return "", err
} else {
if len(concat) > max {
return concat[:max], nil
} else {
return concat, nil
}
}
}
}
}
func join2(s1, s2 string, max int) (string, error) {
if s1 == "" {
return "", errors.New("s1 is empty")
}
if s2 == "" {
return "", errors.New("s2 is empty")
}
concat, err := concatenate(s1, s2)
if err != nil {
return "", err
}
if len(concat) > max {
return concat[:max], nil
}
return concat, nil
}
func concatenate(s1, s2 string) (string, error) {
return "", nil
}

View file

@ -0,0 +1,22 @@
package main
import (
"database/sql"
"log"
"os"
)
var db *sql.DB
func init() {
dataSourceName := os.Getenv("MYSQL_DATA_SOURCE_NAME")
d, err := sql.Open("mysql", dataSourceName)
if err != nil {
log.Panic(err)
}
err = d.Ping()
if err != nil {
log.Panic(err)
}
db = d
}

View file

@ -0,0 +1,20 @@
package main
import (
"fmt"
"github.com/teivah/100-go-mistakes/2-code-project-organization/3-init-functions/redis"
)
func init() {
fmt.Println("init 1")
}
func init() {
fmt.Println("init 2")
}
func main() {
err := redis.Store("foo", "bar")
_ = err
}

View file

@ -0,0 +1,11 @@
package redis
import "fmt"
func init() {
fmt.Println("redis")
}
func Store(key, value string) error {
return nil
}

View file

@ -0,0 +1,12 @@
package main
import "io"
func copySourceToDest(source io.Reader, dest io.Writer) error {
b, err := io.ReadAll(source)
if err != nil {
return err
}
_, err = dest.Write(b)
return err
}

View file

@ -0,0 +1,23 @@
package main
import (
"bytes"
"strings"
"testing"
)
func TestCopySourceToDest(t *testing.T) {
const input = "foo"
source := strings.NewReader(input)
dest := bytes.NewBuffer(make([]byte, 0))
err := copySourceToDest(source, dest)
if err != nil {
t.FailNow()
}
got := dest.String()
if got != input {
t.Errorf("expected: %s, got: %s", input, got)
}
}

View file

@ -0,0 +1,14 @@
package main
type customerStorer interface {
StoreCustomer(Customer) error
}
type CustomerService2 struct {
storer customerStorer
}
func (cs CustomerService2) CreateNewCustomer(id string) error {
customer := Customer{id: id}
return cs.storer.StoreCustomer(customer)
}

View file

@ -0,0 +1,20 @@
package main
type CustomerService struct {
store Store
}
func (cs CustomerService) CreateNewCustomer(id string) error {
customer := Customer{id: id}
return cs.store.StoreCustomer(customer)
}
type Customer struct {
id string
}
type Store struct{}
func (s Store) StoreCustomer(customer Customer) error {
return nil
}

View file

@ -0,0 +1,18 @@
package main
func main() {
var i any
i = 42
i = "foo"
i = struct {
s string
}{
s: "bar",
}
i = f
_ = i
}
func f() {}

View file

@ -0,0 +1,17 @@
package store
func (s *Store) GetContract(id string) (Contract, error) {
return Contract{}, nil
}
func (s *Store) SetContract(id string, contract Contract) error {
return nil
}
func (s *Store) GetCustomer(id string) (Customer, error) {
return Customer{}, nil
}
func (s *Store) SetCustomer(id string, customer Customer) error {
return nil
}

View file

@ -0,0 +1,19 @@
package store
type Customer struct {
// Some fields
}
type Contract struct {
// Some fields
}
type Store struct{}
func (s *Store) Get(id string) (any, error) {
return nil, nil
}
func (s *Store) Set(id string, v any) error {
return nil
}

View file

@ -0,0 +1,54 @@
package main
import "fmt"
func getKeys(m any) ([]any, error) {
switch t := m.(type) {
default:
return nil, fmt.Errorf("unknown type: %T", t)
case map[string]int:
var keys []any
for k := range t {
keys = append(keys, k)
}
return keys, nil
case map[int]string:
// ...
}
return nil, nil
}
func getKeysGenerics[K comparable, V any](m map[K]V) []K {
var keys []K
for k := range m {
keys = append(keys, k)
}
return keys
}
type customConstraint interface {
~int | ~string <1>
}
func getKeysWithConstraing[K customConstraint, V any](m map[K]V) []K {
return nil
}
type Node[T any] struct {
Val T
next *Node[T]
}
func (n *Node[T]) Add(next *Node[T]) {
n.next = next
}
type sliceFn[T any] struct {
s []T
compare func(T, T) bool
}
func (s sliceFn[T]) Len() int { return len(s.s) }
func (s sliceFn[T]) Less(i, j int) bool { return s.compare(s.s[i], s.s[j]) }
func (s sliceFn[T]) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] }

View file

@ -0,0 +1,8 @@
package main
import "fmt"
func main() {
sum := 100 + 0o10
fmt.Println(sum)
}

View file

@ -0,0 +1,50 @@
package main
import "math"
func Inc32(counter int32) int32 {
if counter == math.MaxInt32 {
panic("int32 overflow")
}
return counter + 1
}
func IncInt(counter int) int {
if counter == math.MaxInt {
panic("int overflow")
}
return counter + 1
}
func IncUint(counter uint) uint {
if counter == math.MaxUint {
panic("uint overflow")
}
return counter + 1
}
func AddInt(a, b int) int {
if a > math.MaxInt-b {
panic("int overflow")
}
return a + b
}
func MultiplyInt(a, b int) int {
if a == 0 || b == 0 {
return 0
}
result := a * b
if a == 1 || b == 1 {
return result
}
if a == math.MinInt || b == math.MinInt {
panic("integer overflow")
}
if result/b != a {
panic("integer overflow")
}
return result
}

View file

@ -0,0 +1,24 @@
package main
import "fmt"
func main() {
var n float32 = 1.0001
fmt.Println(n * n)
}
func f1(n int) float64 {
result := 10_000.
for i := 0; i < n; i++ {
result += 1.0001
}
return result
}
func f2(n int) float64 {
result := 0.
for i := 0; i < n; i++ {
result += 1.0001
}
return result + 10_000.
}

View file

@ -0,0 +1,38 @@
package main
import "fmt"
func main() {
s := make([]int, 3, 6)
print(s)
s[1] = 1
print(s)
s = append(s, 2)
print(s)
s = append(s, 3)
s = append(s, 4)
s = append(s, 5)
print(s)
s1 := make([]int, 3, 6)
s2 := s1[1:3]
s1[1] = 1
print(s2)
s2 = append(s2, 2)
print(s1)
print(s2)
s2 = append(s2, 3)
s2 = append(s2, 4)
s2 = append(s2, 5)
print(s1)
print(s2)
}
func print(s []int) {
fmt.Printf("len=%d, cap=%d: %v\n", len(s), cap(s), s)
}

View file

@ -0,0 +1,38 @@
package main
func convertEmptySlice(foos []Foo) []Bar {
bars := make([]Bar, 0)
for _, foo := range foos {
bars = append(bars, fooToBar(foo))
}
return bars
}
func convertGivenCapacity(foos []Foo) []Bar {
n := len(foos)
bars := make([]Bar, 0, n)
for _, foo := range foos {
bars = append(bars, fooToBar(foo))
}
return bars
}
func convertGivenLength(foos []Foo) []Bar {
n := len(foos)
bars := make([]Bar, n)
for i, foo := range foos {
bars[i] = fooToBar(foo)
}
return bars
}
type Foo struct{}
type Bar struct{}
func fooToBar(foo Foo) Bar {
return Bar{}
}

View file

@ -0,0 +1,37 @@
package main
import "testing"
const n = 1_000_000
var global []Bar
func BenchmarkConvert_EmptySlice(b *testing.B) {
var local []Bar
foos := make([]Foo, n)
b.ResetTimer()
for i := 0; i < b.N; i++ {
local = convertEmptySlice(foos)
}
global = local
}
func BenchmarkConvert_GivenCapacity(b *testing.B) {
var local []Bar
foos := make([]Foo, n)
b.ResetTimer()
for i := 0; i < b.N; i++ {
local = convertGivenCapacity(foos)
}
global = local
}
func BenchmarkConvert_GivenLength(b *testing.B) {
var local []Bar
foos := make([]Foo, n)
b.ResetTimer()
for i := 0; i < b.N; i++ {
local = convertGivenLength(foos)
}
global = local
}

View file

@ -0,0 +1,29 @@
package main
import (
"encoding/json"
"fmt"
)
func main() {
var s1 []float32
customer1 := customer{
ID: "foo",
Operations: s1,
}
b, _ := json.Marshal(customer1)
fmt.Println(string(b))
s2 := make([]float32, 0)
customer2 := customer{
ID: "bar",
Operations: s2,
}
b, _ = json.Marshal(customer2)
fmt.Println(string(b))
}
type customer struct {
ID string
Operations []float32
}

View file

@ -0,0 +1,23 @@
package main
import (
"fmt"
)
func main() {
var s []string
log(1, s)
s = []string(nil)
log(2, s)
s = []string{}
log(3, s)
s = make([]string, 0)
log(4, s)
}
func log(i int, s []string) {
fmt.Printf("%d: empty=%t\tnil=%t\n", i, len(s) == 0, s == nil)
}

View file

@ -0,0 +1,29 @@
package main
func handleOperations1(id string) {
operations := getOperations(id)
if operations != nil {
handle(operations)
}
}
func handleOperations2(id string) {
operations := getOperations(id)
if len(operations) != 0 {
handle(operations)
}
}
func getOperations(id string) []float32 {
operations := make([]float32, 0)
if id == "" {
return operations
}
// Add elements to operations
return operations
}
func handle(operations []float32) {}

View file

@ -0,0 +1,23 @@
package main
import "fmt"
func bad() {
src := []int{0, 1, 2}
var dst []int
copy(dst, src)
fmt.Println(dst)
_ = src
_ = dst
}
func correct() {
src := []int{0, 1, 2}
dst := make([]int, len(src))
copy(dst, src)
fmt.Println(dst)
_ = src
_ = dst
}

View file

@ -0,0 +1,36 @@
package main
import "fmt"
func main() {
listing1()
listing2()
listing3()
}
func listing1() {
s := []int{1, 2, 3}
f(s[:2])
fmt.Println(s)
}
func listing2() {
s := []int{1, 2, 3}
sCopy := make([]int, 2)
copy(sCopy, s)
f(sCopy)
result := append(sCopy, s[2])
fmt.Println(result)
}
func listing3() {
s := []int{1, 2, 3}
f(s[:2:2])
fmt.Println(s)
}
func f(s []int) {
_ = append(s, 10)
}

View file

@ -0,0 +1,36 @@
package main
import (
"fmt"
"runtime"
)
func consumeMessages() {
for {
msg := receiveMessage()
// Do something with msg
storeMessageType(getMessageType(msg))
}
}
func getMessageType(msg []byte) []byte {
return msg[:5]
}
func getMessageTypeWithCopy(msg []byte) []byte {
msgType := make([]byte, 5)
copy(msgType, msg)
return msgType
}
func receiveMessage() []byte {
return make([]byte, 1_000_000)
}
func storeMessageType([]byte) {}
func printAlloc() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d KB\n", m.Alloc/1024)
}

View file

@ -0,0 +1,50 @@
package main
import (
"fmt"
"runtime"
)
type Foo struct {
v []byte
}
func main() {
foos := make([]Foo, 1_000)
printAlloc()
for i := 0; i < len(foos); i++ {
foos[i] = Foo{
v: make([]byte, 1024*1024),
}
}
printAlloc()
two := keepFirstTwoElementsOnly(foos)
runtime.GC()
printAlloc()
runtime.KeepAlive(two)
}
func keepFirstTwoElementsOnly(foos []Foo) []Foo {
return foos[:2]
}
func keepFirstTwoElementsOnlyCopy(foos []Foo) []Foo {
res := make([]Foo, 2)
copy(res, foos)
return res
}
func keepFirstTwoElementsOnlyMarkNil(foos []Foo) []Foo {
for i := 2; i < len(foos); i++ {
foos[i].v = nil
}
return foos[:2]
}
func printAlloc() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d KB\n", m.Alloc/1024)
}

View file

@ -0,0 +1,29 @@
package main
import "testing"
const n = 1_000_000
var global map[int]struct{}
func BenchmarkMapWithoutSize(b *testing.B) {
var local map[int]struct{}
for i := 0; i < b.N; i++ {
m := make(map[int]struct{})
for j := 0; j < n; j++ {
m[j] = struct{}{}
}
}
global = local
}
func BenchmarkMapWithSize(b *testing.B) {
var local map[int]struct{}
for i := 0; i < b.N; i++ {
m := make(map[int]struct{}, n)
for j := 0; j < n; j++ {
m[j] = struct{}{}
}
}
global = local
}

View file

@ -0,0 +1,39 @@
package main
import (
"fmt"
"runtime"
)
func main() {
// Init
n := 1_000_000
m := make(map[int][128]byte)
printAlloc()
// Add elements
for i := 0; i < n; i++ {
m[i] = randBytes()
}
printAlloc()
// Remove elements
for i := 0; i < n; i++ {
delete(m, i)
}
// End
runtime.GC()
printAlloc()
runtime.KeepAlive(m)
}
func randBytes() [128]byte {
return [128]byte{}
}
func printAlloc() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("%d MB\n", m.Alloc/1024/1024)
}

View file

@ -0,0 +1,55 @@
package main
import (
"fmt"
"reflect"
)
type customer1 struct {
id string
}
type customer2 struct {
id string
operations []float64
}
func main() {
cust11 := customer1{id: "x"}
cust12 := customer1{id: "x"}
fmt.Println(cust11 == cust12)
cust21 := customer2{id: "x", operations: []float64{1.}}
cust22 := customer2{id: "x", operations: []float64{1.}}
// Doesn't compile
// fmt.Println(cust21 == cust22)
_ = cust21
_ = cust22
var a any = 3
var b any = 3
fmt.Println(a == b)
var cust31 any = customer2{id: "x", operations: []float64{1.}}
var cust32 any = customer2{id: "x", operations: []float64{1.}}
fmt.Println(cust31 == cust32)
cust41 := customer2{id: "x", operations: []float64{1.}}
cust42 := customer2{id: "x", operations: []float64{1.}}
fmt.Println(reflect.DeepEqual(cust41, cust42))
}
func (a customer2) equal(b customer2) bool {
if a.id != b.id {
return false
}
if len(a.operations) != len(b.operations) {
return false
}
for i := 0; i < len(a.operations); i++ {
if a.operations[i] != b.operations[i] {
return false
}
}
return true
}

View file

@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
s := []string{"a", "b", "c"}
for i, v := range s {
fmt.Printf("index=%d, value=%s\n", i, v)
}
for _, v := range s {
fmt.Printf("value=%s\n", v)
}
}

View file

@ -0,0 +1,64 @@
package main
import (
"fmt"
"strings"
)
type account struct {
balance float32
}
func main() {
accounts := createAccounts()
for _, a := range accounts {
a.balance += 1000
}
fmt.Println(accounts)
accounts = createAccounts()
for i := range accounts {
accounts[i].balance += 1000
}
fmt.Println(accounts)
accounts = createAccounts()
for i := 0; i < len(accounts); i++ {
accounts[i].balance += 1000
}
fmt.Println(accounts)
accountsPtr := createAccountsPtr()
for _, a := range accountsPtr {
a.balance += 1000
}
printAccountsPtr(accountsPtr)
}
func createAccounts() []account {
return []account{
{balance: 100.},
{balance: 200.},
{balance: 300.},
}
}
func createAccountsPtr() []*account {
return []*account{
{balance: 100.},
{balance: 200.},
{balance: 300.},
}
}
func printAccountsPtr(accounts []*account) {
sb := strings.Builder{}
sb.WriteString("[")
s := make([]string, len(accounts))
for i, account := range accounts {
s[i] = fmt.Sprintf("{%.0f}", account.balance)
}
sb.WriteString(strings.Join(s, " "))
sb.WriteString("]")
fmt.Println(sb.String())
}

View file

@ -0,0 +1,33 @@
package main
import "fmt"
func listing1() {
a := [3]int{0, 1, 2}
for i, v := range a {
a[2] = 10
if i == 2 {
fmt.Println(v)
}
}
}
func listing2() {
a := [3]int{0, 1, 2}
for i := range a {
a[2] = 10
if i == 2 {
fmt.Println(a[2])
}
}
}
func listing3() {
a := [3]int{0, 1, 2}
for i, v := range &a {
a[2] = 10
if i == 2 {
fmt.Println(v)
}
}
}

View file

@ -0,0 +1,27 @@
package main
import "fmt"
func main() {
ch1 := make(chan int, 3)
go func() {
ch1 <- 0
ch1 <- 1
ch1 <- 2
close(ch1)
}()
ch2 := make(chan int, 3)
go func() {
ch2 <- 10
ch2 <- 11
ch2 <- 12
close(ch2)
}()
ch := ch1
for v := range ch {
fmt.Println(v)
ch = ch2
}
}

View file

@ -0,0 +1,13 @@
package main
func main() {
s1 := []int{0, 1, 2}
for range s1 {
s1 = append(s1, 10)
}
s2 := []int{0, 1, 2}
for i := 0; i < len(s2); i++ {
s2 = append(s2, 10)
}
}

View file

@ -0,0 +1,27 @@
package concepts
type Store struct {
m map[string]*Foo
}
func (s Store) Put(id string, foo *Foo) {
s.m[id] = foo
// ...
}
type Foo struct{}
func updateMapValue(mapValue map[string]LargeStruct, id string) {
value := mapValue[id]
value.foo = "bar"
mapValue[id] = value
}
func updateMapPointer(mapPointer map[string]*LargeStruct, id string) {
mapPointer[id].foo = "bar"
}
type LargeStruct struct {
foo string
_ [1024]int64
}

View file

@ -0,0 +1,51 @@
package main
import "fmt"
type Customer struct {
ID string
Balance float64
}
type Store struct {
m map[string]*Customer
}
func main() {
s := Store{
m: make(map[string]*Customer),
}
s.storeCustomers([]Customer{
{ID: "1", Balance: 10},
{ID: "2", Balance: -10},
{ID: "3", Balance: 0},
})
print(s.m)
}
func (s *Store) storeCustomers(customers []Customer) {
for _, customer := range customers {
fmt.Printf("%p\n", &customer)
s.m[customer.ID] = &customer
}
}
func (s *Store) storeCustomers2(customers []Customer) {
for _, customer := range customers {
current := customer
s.m[current.ID] = &current
}
}
func (s *Store) storeCustomers3(customers []Customer) {
for i := range customers {
customer := &customers[i]
s.m[customer.ID] = customer
}
}
func print(m map[string]*Customer) {
for k, v := range m {
fmt.Printf("key=%s, value=%#v\n", k, v)
}
}

View file

@ -0,0 +1,45 @@
package main
import "fmt"
func listing1() {
m := map[int]bool{
0: true,
1: false,
2: true,
}
for k, v := range m {
if v {
m[10+k] = true
}
}
fmt.Println(m)
}
func listing2() {
m := map[int]bool{
0: true,
1: false,
2: true,
}
m2 := copyMap(m)
for k, v := range m {
m2[k] = v
if v {
m2[10+k] = true
}
}
fmt.Println(m2)
}
func copyMap(m map[int]bool) map[int]bool {
res := make(map[int]bool, len(m))
for k, v := range m {
res[k] = v
}
return res
}

View file

@ -0,0 +1,54 @@
package main
import (
"context"
"fmt"
)
func listing1() {
for i := 0; i < 5; i++ {
fmt.Printf("%d ", i)
switch i {
default:
case 2:
break
}
}
}
func listing2() {
loop:
for i := 0; i < 5; i++ {
fmt.Printf("%d ", i)
switch i {
default:
case 2:
break loop
}
}
}
func listing3(ctx context.Context, ch <-chan int) {
for {
select {
case <-ch:
// Do something
case <-ctx.Done():
break
}
}
}
func listing4(ctx context.Context, ch <-chan int) {
loop:
for {
select {
case <-ch:
// Do something
case <-ctx.Done():
break loop
}
}
}

Some files were not shown because too many files have changed in this diff Show more