Исходники и презентации

This commit is contained in:
2025-05-23 07:26:39 +03:00
parent aa948179d5
commit 02d8430a3a
514 changed files with 13773 additions and 0 deletions

View File

@ -0,0 +1,14 @@
package main
// -l = disable inlining
// -m = print optimization decisions
// go build -gcflags '-l -m'
func getResult() int {
result := 200
return result
}
func main() {
_ = getResult()
}

View File

@ -0,0 +1,14 @@
package main
// -l = disable inlining
// -m = print optimization decisions
// go build -gcflags '-l -m'
func getResult() *int {
result := 200
return &result
}
func main() {
_ = getResult()
}

View File

@ -0,0 +1,15 @@
package main
// -l = disable inlining
// -m = print optimization decisions
// go build -gcflags '-l -m'
func getResult(number *int) int {
result := *number + 200
return result
}
func main() {
number := 100
_ = getResult(&number)
}

View File

@ -0,0 +1,28 @@
package main
import "fmt"
// -l = disable inlining
// -m = print optimization decisions
// go build -gcflags '-l -m'
func printValue(v interface{}) {
fmt.Println(v)
//_, _ = v.(int)
}
func main() {
var num1 int = 10
var str1 string = "Hello"
printValue(num1)
printValue(str1)
var num2 int = 10
var str2 string = "Hello"
var i interface{}
i = num2
i = str2
_ = i
}

View File

@ -0,0 +1,18 @@
package main
// -l = disable inlining
// -m = print optimization decisions
// go build -gcflags '-l -m'
func createPointer() *int {
value2 := new(int)
return value2
}
func main() {
value1 := new(int) // stack
_ = value1
value2 := createPointer() // heap
_ = value2
}

View File

@ -0,0 +1,33 @@
package main
import "testing"
// go test -bench=. -benchmem
type Data struct {
iValue int
sValue string
bValue bool
}
//go:noinline
func NewDataByValue() Data {
return Data{iValue: 100, sValue: "100", bValue: true}
}
//go:noinline
func NewDataByPointer() *Data {
return &Data{iValue: 100, sValue: "100", bValue: true}
}
func BenchmarkNewByValue(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = NewDataByValue()
}
}
func BenchmarkNewByPointer(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = NewDataByPointer()
}
}

View File

@ -0,0 +1,43 @@
package main
import "testing"
// go test -bench=. -benchmem
const bufferSize = 10
type ReaderWithSliceArgument struct{}
func (r ReaderWithSliceArgument) Read(p []byte) (int, error) {
for i := 0; i < bufferSize; i++ {
p[i] = byte(i)
}
return bufferSize, nil
}
type ReaderWithSliceReturn struct{}
func (r ReaderWithSliceReturn) Read(n int) ([]byte, error) {
p := make([]byte, n)
for i := 0; i < n; i++ {
p[i] = byte(i)
}
return p, nil
}
func BenchmarkSliceWithArgument(b *testing.B) {
for i := 0; i < b.N; i++ {
p := make([]byte, bufferSize)
reader := ReaderWithSliceArgument{}
_, _ = reader.Read(p)
}
}
func BenchmarkSliceWithReturn(b *testing.B) {
for i := 0; i < b.N; i++ {
reader := ReaderWithSliceReturn{}
_, _ = reader.Read(bufferSize)
}
}

View File

@ -0,0 +1,28 @@
package main
import "testing"
// go test -bench=. -benchmem
type Data struct {
pointer *int
}
func BenchmarkIteration1(b *testing.B) {
for i := 0; i < b.N; i++ {
var number int
data := &Data{
pointer: &number,
}
_ = data
}
}
func BenchmarkIteration2(b *testing.B) {
for i := 0; i < b.N; i++ {
var number int
data := &Data{}
data.pointer = &number
_ = data
}
}

View File

@ -0,0 +1,26 @@
package main
import (
"fmt"
"unsafe"
)
// For memory blocks larger than 32768 bytes,
// each of them is always composed of multiple
// memory pages. The memory page size used by the
// official standard Go runtime (1.22 versions) is 8192 bytes.
func main() {
var data1 [32769]byte
var data2 [32769]byte
data1Pointer := unsafe.Pointer(&data1)
data2Pointer := unsafe.Pointer(&data2)
fmt.Println("adress:", data1Pointer, data2Pointer)
fmt.Println("size:", unsafe.Sizeof(data1), unsafe.Sizeof(data2))
distance := uintptr(data2Pointer) - uintptr(data1Pointer)
fmt.Println("distance:", distance)
fmt.Println("waste:", distance-unsafe.Sizeof(data1))
}

View File

@ -0,0 +1,24 @@
package main
import (
"fmt"
"testing"
)
var result string
var buffer []byte = make([]byte, 33)
func Concat(b *testing.B) {
for i := 0; i < b.N; i++ {
result = string(buffer) + string(buffer)
}
}
func main() {
b := testing.Benchmark(Concat)
fmt.Println(b.AllocsPerOp()) // 3
fmt.Println(b.AllocedBytesPerOp()) // 176
// alocated 176 bytes = 48 (not 33) + 48 (not 33) + 80 (not 33 + 33 = 66)
// waste = 15 + 15 + 14 = 44 bytes (25% waste)
}

View File

@ -0,0 +1,30 @@
package main
// GOEXPERIMENT=arenas go run main.go
// go run -tags goexperiment.arenas main.go
import (
"arena"
)
type Data struct {
deposit int
credit int
}
func main() {
a := arena.NewArena()
defer a.Free()
value := arena.New[int64](a)
_ = value
data := arena.New[Data](a)
_ = data
slice := arena.MakeSlice[int32](a, 0, 10)
_ = slice
cloned := arena.Clone[*Data](data) // moved to heap
_ = cloned
}

View File

@ -0,0 +1,24 @@
package main
// GOEXPERIMENT=arenas go run main.go
// go run -tags goexperiment.arenas main.go
import (
"arena"
)
type Data struct {
value int
operaions []int
}
func main() {
a := arena.NewArena()
defer a.Free()
// Arenas will not allocate all reference types automatically
operations := arena.MakeSlice[int](a, 0, 100)
data := arena.New[Data](a)
data.operaions = operations
_ = data
}

View File

@ -0,0 +1,18 @@
package main
// GOEXPERIMENT=arenas go run main.go
// go run -tags goexperiment.arenas main.go
import (
"arena"
)
func main() {
mem := arena.NewArena()
defer mem.Free()
slice := arena.NewSlice[int](mem, 0, 5)
slice = append(slice, 1, 2, 3, 4, 5)
slice = append(slice, 6) // moved to heap
}

View File

@ -0,0 +1,23 @@
package main
// GOEXPERIMENT=arenas go run main.go
// go run -tags goexperiment.arenas main.go
import (
"arena"
"fmt"
)
type Data struct {
deposit int
credit int
}
func main() {
a := arena.NewArena()
data := arena.New[Data](a)
a.Free()
// use after free
fmt.Println(data)
}

View File

@ -0,0 +1,22 @@
package main
import "fmt"
// go run main.go
// GOGC=off go run main.go
var data []byte
func main() {
count := 0
for {
data = make([]byte, 1<<30)
/*for idx := 0; idx < 1<<30; idx += 4096 {
data[idx] = 100
}*/
fmt.Println("allocated GB:", count)
count++
}
}

View File

@ -0,0 +1,74 @@
package main
import (
"errors"
"fmt"
"unsafe"
)
type LinearAllocator struct {
data []byte
}
func NewLinearAllocator(capacity int) (LinearAllocator, error) {
if capacity <= 0 {
return LinearAllocator{}, errors.New("incorrect capacity")
}
return LinearAllocator{
data: make([]byte, 0, capacity),
}, nil
}
func (a *LinearAllocator) Allocate(size int) (unsafe.Pointer, error) {
previousLength := len(a.data)
newLength := previousLength + size
if newLength > cap(a.data) {
// can increase capacity
return nil, errors.New("not enough memory")
}
a.data = a.data[:newLength]
pointer := unsafe.Pointer(&a.data[previousLength])
return pointer, nil
}
// not supported by this kind of allocator
// func (a *LinearAllocator) Deallocate(pointer unsafe.Pointer) error {}
func (a *LinearAllocator) Free() {
a.data = a.data[:0]
}
func store[T any](pointer unsafe.Pointer, value T) {
*(*T)(pointer) = value
}
func load[T any](pointer unsafe.Pointer) T {
return *(*T)(pointer)
}
func main() {
const MB = 1 << 20
allocator, err := NewLinearAllocator(MB)
if err != nil {
// handling...
}
defer allocator.Free()
pointer1, _ := allocator.Allocate(2)
pointer2, _ := allocator.Allocate(4)
store[int16](pointer1, 100)
store[int32](pointer2, 200)
value1 := load[int16](pointer1)
value2 := load[int32](pointer2)
fmt.Println("value1:", value1)
fmt.Println("value2:", value2)
fmt.Println("address1:", pointer1)
fmt.Println("address2:", pointer2)
}

View File

@ -0,0 +1,26 @@
package main
// go test -bench=. allocations_test.go -benchmem
import (
"testing"
)
//go:noinline
func Initialize(value *int) {
*value = 1000
}
func BenchmarkWithoutLoopAllocation(b *testing.B) {
var value int
for i := 0; i < b.N; i++ {
Initialize(&value)
}
}
func BenchmarkWithLoopAllocation(b *testing.B) {
for i := 0; i < b.N; i++ {
var value int
Initialize(&value)
}
}

View File

@ -0,0 +1,50 @@
package main
// go test -bench=. pool_test.go -benchmem
import (
"sync"
"testing"
)
type Person struct {
name string
}
type PersonsPool struct {
pool sync.Pool
}
func NewPersonsPool() *PersonsPool {
return &PersonsPool{
pool: sync.Pool{
New: func() interface{} { return new(Person) },
},
}
}
func (p *PersonsPool) Get() *Person {
return p.pool.Get().(*Person)
}
func (p *PersonsPool) Put(person *Person) {
p.pool.Put(person)
}
var gPerson *Person
func BenchmarkWithPool(b *testing.B) {
pool := NewPersonsPool()
for i := 0; i < b.N; i++ {
person := pool.Get()
person.name = "Ivan" // need to reset values
gPerson = person
pool.Put(person)
}
}
func BenchmarkWithoutPool(b *testing.B) {
for i := 0; i < b.N; i++ {
person := &Person{name: "Ivan"}
gPerson = person
}
}

View File

@ -0,0 +1,100 @@
package main
import (
"errors"
"fmt"
"unsafe"
)
type PoolAllocator struct {
objectPool []byte
freeObjects map[unsafe.Pointer]struct{}
objectSize int
}
func NewPoolAllocator(capacity int, objectSize int) (PoolAllocator, error) {
if capacity <= 0 || objectSize <= 0 || capacity%objectSize != 0 {
return PoolAllocator{}, errors.New("incorrect argumnets")
}
allocator := PoolAllocator{
objectPool: make([]byte, capacity),
freeObjects: make(map[unsafe.Pointer]struct{}, capacity/objectSize),
objectSize: objectSize,
}
allocator.resetMemoryState()
return allocator, nil
}
func (a *PoolAllocator) Allocate() (unsafe.Pointer, error) {
if len(a.freeObjects) == 0 {
// can increase capacity
return nil, errors.New("not enough memory")
}
var pointer unsafe.Pointer
for freePointer := range a.freeObjects {
pointer = freePointer
break
}
delete(a.freeObjects, pointer)
return pointer, nil
}
func (a *PoolAllocator) Deallocate(pointer unsafe.Pointer) error {
if pointer == nil {
return errors.New("incorrect pointer")
}
// potentionally incorrect pointer
a.freeObjects[pointer] = struct{}{}
return nil
}
func (a *PoolAllocator) Free() {
a.resetMemoryState()
}
func (a *PoolAllocator) resetMemoryState() {
for offset := 0; offset < len(a.objectPool); offset += a.objectSize {
pointer := unsafe.Pointer(&a.objectPool[offset])
a.freeObjects[pointer] = struct{}{}
}
}
func store[T any](pointer unsafe.Pointer, value T) {
*(*T)(pointer) = value
}
func load[T any](pointer unsafe.Pointer) T {
return *(*T)(pointer)
}
func main() {
const KB = 1 << 10
allocator, err := NewPoolAllocator(KB, 4)
if err != nil {
// handling...
}
defer allocator.Free()
pointer1, _ := allocator.Allocate()
pointer2, _ := allocator.Allocate()
store[int32](pointer1, 100)
store[int32](pointer2, 200)
value1 := load[int32](pointer1)
value2 := load[int32](pointer2)
fmt.Println("value1:", value1)
fmt.Println("value2:", value2)
fmt.Println("address1:", pointer1)
fmt.Println("address2:", pointer2)
allocator.Deallocate(pointer1)
allocator.Deallocate(pointer2)
}

View File

@ -0,0 +1,100 @@
package main
import (
"errors"
"fmt"
"math"
"unsafe"
)
const headerSize = 2
type StackAllocator struct {
data []byte
}
func NewStackAllocator(capacity int) (StackAllocator, error) {
if capacity <= 0 {
return StackAllocator{}, errors.New("incorrect capacity")
}
return StackAllocator{
data: make([]byte, 0, capacity),
}, nil
}
func (a *StackAllocator) Allocate(size int) (unsafe.Pointer, error) {
if size > math.MaxInt16 {
// can increase header size
return nil, errors.New("incorrect size")
}
previousLength := len(a.data)
newLength := previousLength + headerSize + size
if newLength > cap(a.data) {
// can increase capacity
return nil, errors.New("not enough memory")
}
a.data = a.data[:newLength]
header := unsafe.Pointer(&a.data[previousLength])
pointer := unsafe.Pointer(&a.data[previousLength+headerSize])
*(*int16)(header) = int16(size)
return pointer, nil
}
func (a *StackAllocator) Deallocate(pointer unsafe.Pointer) error {
// can deallocate without pointer
if pointer == nil {
return errors.New("incorrect pointer")
}
header := unsafe.Add(pointer, -headerSize)
size := *(*int16)(header)
previousLength := len(a.data)
newLength := previousLength - headerSize - int(size)
a.data = a.data[:newLength]
return nil
}
func (a *StackAllocator) Free() {
a.data = a.data[:0]
}
func store[T any](pointer unsafe.Pointer, value T) {
*(*T)(pointer) = value
}
func load[T any](pointer unsafe.Pointer) T {
return *(*T)(pointer)
}
func main() {
const KB = 1 << 10
allocator, err := NewStackAllocator(KB)
if err != nil {
// handling...
}
defer allocator.Free()
pointer1, _ := allocator.Allocate(2)
defer allocator.Deallocate(pointer1)
pointer2, _ := allocator.Allocate(4)
defer allocator.Deallocate(pointer2)
store[int16](pointer1, 100)
store[int32](pointer2, 200)
value1 := load[int16](pointer1)
value2 := load[int32](pointer2)
fmt.Println("value1:", value1)
fmt.Println("value2:", value2)
fmt.Println("address1:", pointer1)
fmt.Println("address2:", pointer2)
}

View File

@ -0,0 +1,20 @@
package main
// -l = disable inlining
// -m = print optimization decisions
// go build -gcflags '-l -m'
// go run -gcflags '-l' main.go
func process(index int) byte {
var data [1 << 20]byte
return data[index]
}
func main() {
var index int = 100
pointer := &index
println("pointer:", pointer)
process(index)
println("pointer:", pointer)
}

View File

@ -0,0 +1,38 @@
package main
import (
"fmt"
"sync"
)
func notifier(signals chan int) {
close(signals)
}
func subscriber(signals chan int) {
<-signals
fmt.Println("signaled")
}
func main() {
signals := make(chan int)
wg := sync.WaitGroup{}
wg.Add(3)
go func() {
defer wg.Done()
notifier(signals)
}()
go func() {
defer wg.Done()
subscriber(signals)
}()
go func() {
defer wg.Done()
subscriber(signals)
}()
wg.Wait()
}

View File

@ -0,0 +1,7 @@
package main
func main() {
ch := make(chan int, 2)
ch <- 100
ch <- 100
}

View File

@ -0,0 +1,21 @@
package main
import "sync"
// go run -race main.go
var buffer chan int
func main() {
wg := sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go func() {
defer wg.Done()
buffer = make(chan int)
}()
}
wg.Wait()
}

View File

@ -0,0 +1,21 @@
package main
import (
"fmt"
"time"
)
// Describe blocking
func async(ch chan string) {
time.Sleep(2 * time.Second)
ch <- "async result"
}
func main() {
ch := make(chan string)
go async(ch)
// ...
result := <-ch
fmt.Println(result)
}

View File

@ -0,0 +1,14 @@
package main
import "fmt"
func main() {
source := make(chan int)
clone := source
go func() {
source <- 1
}()
fmt.Println(<-clone)
}

View File

@ -0,0 +1,46 @@
package main
import (
"sync"
)
var actions int
var mutex sync.Mutex
var buffer chan struct{}
func consumer() {
for i := 0; i < 1000; i++ {
mutex.Lock()
actions++
<-buffer
mutex.Unlock()
}
}
func producer() {
for i := 0; i < 1000; i++ {
buffer <- struct{}{}
mutex.Lock()
actions++
mutex.Unlock()
}
}
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
buffer = make(chan struct{}, 1)
go func() {
defer wg.Done()
consumer()
}()
go func() {
defer wg.Done()
producer()
}()
wg.Wait()
}

View File

@ -0,0 +1,26 @@
package main
import (
"fmt"
"log"
"time"
)
func main() {
doWork := func(strings <-chan string) {
go func() {
for str := range strings {
fmt.Println(str)
}
log.Println("doWork exited")
}()
}
strings := make(chan string)
doWork(strings)
strings <- "Test"
time.Sleep(time.Second)
fmt.Println("Done")
}

View File

@ -0,0 +1,15 @@
package main
// Need to show solution and describe close
// First-response-wins strategy
func request() int {
ch := make(chan int)
for i := 0; i < 5; i++ {
go func() {
ch <- i // 4 goroutines will be blocked
}()
}
return <-ch
}

View File

@ -0,0 +1,22 @@
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
ch <- 1
}()
go func() {
ch <- 1
}()
value := 0
value += <-ch
value += <-ch
fmt.Println(value)
}

View File

@ -0,0 +1,27 @@
package main
import (
"fmt"
"sync"
)
func main() {
mutex := sync.Mutex{}
wg := sync.WaitGroup{}
wg.Add(2)
value := 0
for i := 0; i < 2; i++ {
go func() {
defer wg.Done()
mutex.Lock()
value++
mutex.Unlock()
}()
}
wg.Wait()
fmt.Println(value)
}

View File

@ -0,0 +1,19 @@
package main
import "fmt"
func IsClosed(ch chan int) bool {
select {
case <-ch:
return true
default:
return false
}
}
func main() {
ch := make(chan int)
fmt.Println(IsClosed(ch))
close(ch)
fmt.Println(IsClosed(ch))
}

View File

@ -0,0 +1,22 @@
package main
import "fmt"
// Need to show solution
func IsClosed(ch chan int) bool {
select {
case <-ch:
return true
default:
return false
}
}
func main() {
ch := make(chan int, 1)
ch <- 1
fmt.Println(IsClosed(ch))
close(ch)
fmt.Println(IsClosed(ch))
}

View File

@ -0,0 +1,47 @@
package main
import (
"fmt"
"sync"
)
// Need to show solution
func WaitToClose(lhs, rhs chan struct{}) {
lhsClosed, rhsClosed := false, false
for !lhsClosed || !rhsClosed {
select {
case _, ok := <-lhs:
fmt.Println("lhs", ok)
if !ok {
lhsClosed = true
}
case _, ok := <-rhs:
fmt.Println("rhs", ok)
if !ok {
rhsClosed = true
}
}
}
}
func main() {
lhs := make(chan struct{}, 1)
rhs := make(chan struct{}, 1)
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer wg.Done()
WaitToClose(lhs, rhs)
}()
lhs <- struct{}{}
rhs <- struct{}{}
close(lhs)
close(rhs)
wg.Wait()
}

View File

@ -0,0 +1,19 @@
package main
import "fmt"
func main() {
ch := make(chan int, 1)
for done := false; !done; {
select {
default:
fmt.Println(3)
done = true
case <-ch:
fmt.Println(2)
ch = nil
case ch <- 1:
fmt.Println(1)
}
}
}

View File

@ -0,0 +1,27 @@
package main
func tryToReadFromChannel(ch chan string) (string, bool) {
select {
case value := <-ch:
return value, true
default:
return "", false
}
}
func tryToWriteToChannel(ch chan string, value string) bool {
select {
case ch <- value:
return true
default:
return false
}
}
func tryToReadOrWrite(ch1 chan string, ch2 chan string) {
select {
case <-ch1:
case ch2 <- "test":
default:
}
}

View File

@ -0,0 +1,19 @@
package main
func tryToReadFromChannel(ch chan string) (string, bool) {
if len(ch) != 0 {
value := <-ch
return value, true
} else {
return "", false
}
}
func tryToWriteToChannel(ch chan string, value string) bool {
if len(ch) < cap(ch) {
ch <- value
return true
} else {
return false
}
}

View File

@ -0,0 +1,91 @@
package main
import (
"fmt"
)
func writeToNilChannel() {
var ch chan int
ch <- 1
}
func writeToClosedChannel() {
ch := make(chan int, 2)
close(ch)
ch <- 20
}
// Descibe read after close
func readFromChannel() {
ch := make(chan int, 2)
ch <- 10
ch <- 20
val, ok := <-ch
fmt.Println(val, ok)
close(ch)
val, ok = <-ch
fmt.Println(val, ok)
val, ok = <-ch
fmt.Println(val, ok)
}
func readAnyChannels() {
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
ch1 <- 100
}()
go func() {
ch2 <- 200
}()
select {
case val1 := <-ch1:
fmt.Println(val1)
case val2 := <-ch2:
fmt.Println(val2)
}
}
func readFromNilChannel() {
var ch chan int
<-ch
}
func rangeNilChannel() {
var ch chan int
for range ch {
}
}
func closeNilChannel() {
var ch chan int
close(ch)
}
func closeChannelAnyTimes() {
ch := make(chan int)
close(ch)
close(ch)
}
func compareChannels() {
ch1 := make(chan int)
ch2 := make(chan int)
equal1 := ch1 == ch2
equal2 := ch1 == ch1
fmt.Println(equal1)
fmt.Println(equal2)
}
func main() {
}

View File

@ -0,0 +1,33 @@
package main
import (
"fmt"
"time"
)
// Need to show solution
func producer(ch chan<- int) {
for {
ch <- 1
time.Sleep(time.Second)
}
}
func main() {
ch1 := make(chan int) // more prioritized
ch2 := make(chan int)
go producer(ch1)
go producer(ch2)
for {
select {
case value := <-ch1:
fmt.Println(value)
return
case value := <-ch2:
fmt.Println(value)
}
}
}

View File

@ -0,0 +1,27 @@
package main
import "fmt"
func main() {
ch1 := make(chan struct{}, 1)
ch2 := make(chan struct{}, 1)
close(ch1)
close(ch2)
ch1Value := 0.0
ch2Value := 0.0
for i := 0; i < 100000; i++ {
select {
case <-ch1:
ch1Value++
case <-ch1:
ch1Value++
case <-ch2:
ch2Value++
}
}
fmt.Println(ch1Value / ch2Value)
}

View File

@ -0,0 +1,51 @@
package main
import (
"fmt"
"sync"
)
func producer(ch chan int) {
defer close(ch)
for i := 0; i < 5; i++ {
ch <- i
}
}
func consumer(ch chan int) {
/*
for {
select {
case value, opened := <-ch:
if !opened {
return
}
fmt.Println(value)
}
}
*/
for value := range ch { // syntax sugar
fmt.Println(value)
}
}
func main() {
ch := make(chan int)
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
producer(ch)
}()
go func() {
defer wg.Done()
consumer(ch)
}()
wg.Wait()
}

View File

@ -0,0 +1,36 @@
package main
import (
"fmt"
"time"
)
func async1() chan string {
ch := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch <- "async1 result"
}()
return ch
}
func async2() chan string {
ch := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch <- "async2 result"
}()
return ch
}
func main() {
ch1 := async1()
ch2 := async2()
select {
case result := <-ch1:
fmt.Println(result)
case result := <-ch2:
fmt.Println(result)
}
}

View File

@ -0,0 +1,29 @@
package main
func way1() {
make(chan struct{}) <- struct{}{}
// or
make(chan<- struct{}) <- struct{}{}
}
func way2() {
<-make(chan struct{})
// or
<-make(<-chan struct{})
// or
for range make(<-chan struct{}) {
}
}
func way3() {
chan struct{}(nil) <- struct{}{}
// or
<-chan struct{}(nil)
// or
for range chan struct{}(nil) {
}
}
func way4() {
select {}
}

View File

@ -0,0 +1,33 @@
package main
import "fmt"
func main() {
data := make(chan int)
go func() {
for i := 1; i <= 4; i++ {
data <- i
}
close(data)
}()
for {
value := 0
opened := true
select {
case value, opened = <-data:
if value == 2 {
continue
} else if value == 3 {
break
}
if !opened {
return
}
}
fmt.Println(value)
}
}

View File

@ -0,0 +1,15 @@
package main
import "runtime"
func doSomething() {
for {
runtime.Gosched()
}
}
func main() {
go doSomething()
go doSomething()
select {}
}

View File

@ -0,0 +1,38 @@
package main
import (
"fmt"
"time"
)
// Need to show solution
func FetchData1() chan int {
ch := make(chan int)
go func() {
time.Sleep(time.Second * 2)
ch <- 10
}()
return ch
}
func FetchData2() chan int {
ch := make(chan int)
go func() {
time.Sleep(time.Second * 2)
ch <- 20
}()
return ch
}
func Process(value1, value2 int) {
// Processing...
}
func main() {
start := time.Now()
Process(<-FetchData1(), <-FetchData2())
fmt.Println(time.Now().Sub(start))
}

View File

@ -0,0 +1,33 @@
package main
import (
"fmt"
"sync"
)
func notifier(signals chan struct{}) {
signals <- struct{}{}
}
func subscriber(signals chan struct{}) {
<-signals
fmt.Println("signaled")
}
func main() {
signals := make(chan struct{})
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
notifier(signals)
}()
go func() {
defer wg.Done()
subscriber(signals)
}()
wg.Wait()
}

View File

@ -0,0 +1,19 @@
package main
import "fmt"
func in(in chan<- int) {
in <- 100
close(in)
}
func out(out <-chan int) {
fmt.Println(<-out)
}
func main() {
var ch = make(chan int, 1)
in(ch)
out(ch)
}

View File

@ -0,0 +1,19 @@
package main
import (
"time"
)
func main() {
ch := make(chan int)
go func() {
ch <- 1
}()
time.Sleep(500 * time.Millisecond)
close(ch)
<-ch
time.Sleep(100 * time.Millisecond)
}

View File

@ -0,0 +1,29 @@
package main
import (
"context"
"fmt"
"time"
)
// context.AfterFunc
func WithCtxAfterFunc(ctx context.Context, action func()) {
if action != nil {
go func() {
<-ctx.Done()
action()
}()
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
WithCtxAfterFunc(ctx, func() {
fmt.Println("after")
})
cancel()
time.Sleep(100 * time.Millisecond)
}

View File

@ -0,0 +1,17 @@
package main
import "context"
func incorrectCheck(ctx context.Context, stream <-chan string) {
data := <-stream
_ = data
}
func correctCheck(ctx context.Context, stream <-chan string) {
select {
case data := <-stream:
_ = data
case <-ctx.Done():
return
}
}

View File

@ -0,0 +1,26 @@
package main
import (
"context"
"time"
)
func Query(string) string
func DoQeury(qyeryStr string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
defer cancel()
var resultCh chan string
go func() {
result := Query(qyeryStr)
resultCh <- result
}()
select {
case <-ctx.Done():
return "", ctx.Err()
case result := <-resultCh:
return result, nil
}
}

View File

@ -0,0 +1,29 @@
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
makeRequest(ctx)
}
func makeRequest(ctx context.Context) {
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
newCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
select {
case <-newCtx.Done():
fmt.Println("canceled")
case <-timer.C:
fmt.Println("timer")
}
}

View File

@ -0,0 +1,19 @@
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, cancel = context.WithCancel(ctx)
cancel()
if ctx.Err() != nil {
fmt.Println("canceled")
}
}

View File

@ -0,0 +1,44 @@
package main
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
)
func receiveWeather(ctx context.Context, result chan struct{}, idx int) {
randomTime := time.Duration(rand.Intn(5000)) * time.Millisecond
timer := time.NewTimer(randomTime)
defer timer.Stop()
select {
case <-timer.C:
fmt.Printf("finished: %d\n", idx)
result <- struct{}{}
case <-ctx.Done():
fmt.Printf("canceled: %d\n", idx)
}
}
func main() {
wg := sync.WaitGroup{}
wg.Add(10)
ctx, cancel := context.WithCancel(context.Background())
result := make(chan struct{}, 10)
for i := 0; i < 10; i++ {
go func(idx int) {
defer wg.Done()
receiveWeather(ctx, result, idx)
}(i)
}
<-result
cancel()
wg.Wait()
}

View File

@ -0,0 +1,15 @@
package main
import (
"context"
"errors"
"fmt"
)
func main() {
ctx, cancel := context.WithCancelCause(context.Background())
cancel(errors.New("error"))
fmt.Println(ctx.Err())
fmt.Println(context.Cause(ctx))
}

View File

@ -0,0 +1,22 @@
package main
import (
"context"
"fmt"
"net/http"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://example.com", nil)
if err != nil {
fmt.Println(err.Error())
}
if _, err = http.DefaultClient.Do(req); err != nil {
fmt.Println(err.Error())
}
}

View File

@ -0,0 +1,34 @@
package main
import (
"context"
"fmt"
"net/http"
)
func main() {
helloWorldHandler := http.HandlerFunc(handle)
http.Handle("/welcome", injectTraceID(helloWorldHandler))
_ = http.ListenAndServe(":8080", nil)
}
func handle(_ http.ResponseWriter, r *http.Request) {
value, ok := r.Context().Value("trace_id").(string)
if ok {
fmt.Println(value)
}
makeRequest(r.Context())
}
func makeRequest(_ context.Context) {
// requesting to database with context
}
func injectTraceID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "trace_id", "12-21-33")
req := r.WithContext(ctx)
next.ServeHTTP(w, req)
})
}

View File

@ -0,0 +1,26 @@
package main
import (
"context"
"fmt"
"time"
)
func makeRequest(ctx context.Context) {
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
fmt.Println("finished")
case <-ctx.Done():
fmt.Println("canceled")
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
makeRequest(ctx)
}

View File

@ -0,0 +1,18 @@
package main
import (
"context"
"errors"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeoutCause(context.Background(), time.Second, errors.New("timeout"))
defer cancel() // show difference
<-ctx.Done()
fmt.Println(ctx.Err())
fmt.Println(context.Cause(ctx))
}

View File

@ -0,0 +1,81 @@
package main
import (
"errors"
"fmt"
"sync/atomic"
"time"
)
type Context struct {
done chan struct{}
closed int32
}
func WithTimeout(parent Context, duration time.Duration) (*Context, func()) {
if atomic.LoadInt32(&parent.closed) == 1 {
return nil, nil // don't use nil
}
ctx := &Context{
done: make(chan struct{}),
}
cancel := func() {
if atomic.CompareAndSwapInt32(&ctx.closed, 0, 1) {
close(ctx.done)
}
}
go func() {
timer := time.NewTimer(duration)
defer timer.Stop()
select {
case <-parent.Done():
case <-timer.C:
}
cancel()
}()
return ctx, cancel
}
func (c *Context) Done() <-chan struct{} {
return c.done
}
func (c *Context) Err() error {
select {
case <-c.done:
return errors.New("context deadline exceeded")
default:
return nil
}
}
func (c *Context) Deadline() (time.Time, bool) {
// not implemented
return time.Time{}, false
}
func (c *Context) Value(any) any {
// not implemented
return nil
}
func main() {
ctx, cancel := WithTimeout(Context{}, time.Second)
defer cancel()
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case <-timer.C:
fmt.Println("finished")
case <-ctx.Done():
fmt.Println("canceled")
}
}

View File

@ -0,0 +1,29 @@
package main
import (
"context"
"fmt"
)
func main() {
traceCtx := context.WithValue(context.Background(), "trace_id", "12-21-33")
makeRequest(traceCtx)
oldValue, ok := traceCtx.Value("trace_id").(string)
if ok {
fmt.Println("mainValue", oldValue)
}
}
func makeRequest(ctx context.Context) {
oldValue, ok := ctx.Value("trace_id").(string)
if ok {
fmt.Println("oldValue", oldValue)
}
newCtx := context.WithValue(ctx, "trace_id", "22-22-22")
newValue, ok := newCtx.Value("trace_id").(string)
if ok {
fmt.Println("newValue", newValue)
}
}

View File

@ -0,0 +1,26 @@
package main
import (
"context"
"fmt"
)
func main() {
traceCtx := context.WithValue(context.Background(), "trace_id", "12-21-33")
makeRequest(traceCtx)
}
func makeRequest(ctx context.Context) {
oldValue, ok := ctx.Value("trace_id").(string)
if ok {
fmt.Println(oldValue)
}
newCtx, cancel := context.WithCancel(ctx)
defer cancel()
newValue, ok := newCtx.Value("trace_id").(string)
if ok {
fmt.Println(newValue)
}
}

View File

@ -0,0 +1,27 @@
package main
import (
"context"
"fmt"
)
func main() {
{
ctx := context.WithValue(context.Background(), "key", "value1")
ctx = context.WithValue(ctx, "key", "value2")
fmt.Println("string =", ctx.Value("key").(string))
}
{
type key1 string // type definition, not type alias
type key2 string // type definition, not type alias
const k1 key1 = "key"
const k2 key2 = "key"
ctx := context.WithValue(context.Background(), k1, "value1")
ctx = context.WithValue(ctx, k2, "value2")
fmt.Println("key1 =", ctx.Value(k1).(string))
fmt.Println("key2 =", ctx.Value(k2).(string))
}
}

View File

@ -0,0 +1,17 @@
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
innerCtx := context.WithoutCancel(ctx)
cancel()
if innerCtx.Err() != nil {
fmt.Println("canceled")
}
}

View File

@ -0,0 +1,5 @@
module errgroup
go 1.20
require golang.org/x/sync v0.6.0

View File

@ -0,0 +1,2 @@
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=

View File

@ -0,0 +1,39 @@
package main
import (
"context"
"errors"
"fmt"
"math/rand"
"time"
"golang.org/x/sync/errgroup"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
group, groupCtx := errgroup.WithContext(ctx)
for i := 0; i < 10; i++ {
group.Go(func() error {
timeout := time.Second * time.Duration(rand.Intn(10))
timer := time.NewTimer(timeout)
defer timer.Stop()
select {
case <-timer.C:
fmt.Println("timeout")
return errors.New("error")
case <-groupCtx.Done():
fmt.Println("canceled")
return nil
}
})
}
if err := group.Wait(); err != nil {
fmt.Println(err.Error())
}
}

View File

@ -0,0 +1,43 @@
package main
import (
"context"
"fmt"
"io"
"log"
"net/http"
"os"
"os/signal"
"time"
)
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "hello world\n")
})
server := &http.Server{
Addr: ":8888",
}
go func() {
err := server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
log.Print(err.Error()) // exit
}
}()
<-ctx.Done()
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
cancel()
if err := server.Shutdown(ctx); err != nil {
log.Print(err.Error())
}
fmt.Println("canceled")
}

View File

@ -0,0 +1,15 @@
package main
import (
"context"
)
func process(ctx context.Context) {
if ctx.Err() != nil {
// handling...
}
}
func main() {
process(nil)
}

View File

@ -0,0 +1,18 @@
package main
import "context"
func WithContexCheck(ctx context.Context, action func()) {
if action == nil || ctx.Err() != nil {
return
}
action()
}
func main() {
ctx := context.Background()
WithContexCheck(ctx, func() {
// do something
})
}

View File

@ -0,0 +1,36 @@
package main
import "fmt"
const (
OpenModeIn = 1 // 0000 0001
OpenModeOut = 2 // 0000 0010
OpenModeAppend = 4 // 0000 0100
OpenModeBinary = 8 // 0000 1000
// sugar for prepared masks
OpenModeInAndOut = OpenModeIn | OpenModeOut // 0000 0001 + 0000 0010 = 0000 0011
)
func Open(filename string, mask int8) {
if mask&OpenModeIn != 0 {
fmt.Println("in mode")
}
if mask&OpenModeOut != 0 {
fmt.Println("out mode")
}
if mask&OpenModeAppend != 0 {
fmt.Println("append mode")
}
if mask&OpenModeBinary != 0 {
fmt.Println("binary mode")
}
// implementation...
}
func main() {
Open("data.bin", OpenModeIn|OpenModeBinary) // 0000 1001
Open("data.bin", OpenModeIn|OpenModeOut) // 0000 0011
Open("data.bin", OpenModeAppend) // 0000 0100
}

View File

@ -0,0 +1,17 @@
package main
func IsSetBit(number, index int) bool {
return (number & (1 << index)) != 0
}
func SetBit(number, index int) int {
return number | (1 << index)
}
func InverseBit(number, index int) int {
return number ^ (1 << index)
}
func ResetBit(number, index int) int {
return number & ^(1 << index)
}

View File

@ -0,0 +1,32 @@
package main
// 0000 0001 -> есть кальяны
// 0000 0010 -> можно с животными
// 0000 0100 -> есть виранда
// 0000 1000 -> есть алкоголь
// 0001 0000 -> есть живая музыка
func searchRestaurants(pattern int8, bitmaps []int8) []int {
var indexes []int
for idx, bitmap := range bitmaps {
if bitmap^pattern == 0 {
indexes = append(indexes, idx)
}
}
return indexes
}
func main() {
restaurants := []int8{
0b00001101,
0b00000010,
0b00010000,
0b00011111,
0b00001001,
}
pattern := int8(0b00011000)
indexes := searchRestaurants(pattern, restaurants)
_ = indexes
}

View File

@ -0,0 +1,39 @@
package main
import "fmt"
type Mode struct {
OpenModeIn bool
OpenModeOut bool
OpenModeAppend bool
OpenModeBinary bool
}
var (
OpenModeInBinary = Mode{OpenModeIn: true, OpenModeBinary: true}
OpenModeInOut = Mode{OpenModeIn: true, OpenModeOut: true}
OpenModeAppend = Mode{OpenModeAppend: true}
)
func Open(filename string, mode Mode) {
if mode.OpenModeIn {
fmt.Println("in mode")
}
if mode.OpenModeOut {
fmt.Println("out mode")
}
if mode.OpenModeAppend {
fmt.Println("append mode")
}
if mode.OpenModeBinary {
fmt.Println("binary mode")
}
// implementation...
}
func main() {
Open("data.bin", OpenModeInBinary)
Open("data.bin", OpenModeInOut)
Open("data.bin", OpenModeAppend)
}

View File

@ -0,0 +1,31 @@
package main
import (
"math"
"testing"
)
// go test -bench=. conversion_test.go
var result int
func BenchmarkConversion1(b *testing.B) {
for i := 0; i < b.N; i++ {
result = 10 << 20
_ = result
}
}
func BenchmarkConversion2(b *testing.B) {
for i := 0; i < b.N; i++ {
result = 10 * 1024 * 1024
_ = result
}
}
func BenchmarkConversion3(b *testing.B) {
for i := 0; i < b.N; i++ {
result = 10 * (int)(math.Pow(2, 20))
_ = result
}
}

View File

@ -0,0 +1,68 @@
package main
import (
"testing"
)
// go test -bench=. check_test.go
func HasDuplicatesFrom1To7WithBits(data []int) bool {
var lookup int8
for _, number := range data {
if lookup&(1<<number) != 0 {
return true
}
lookup |= 1 << number
}
return false
}
func HasDuplicatesFrom1To7WithArray(data []int) bool {
var lookup [8]int8
for _, number := range data {
if lookup[number] == 1 {
return true
}
lookup[number] = 1
}
return false
}
func HasDuplicatesFrom1To7WithHashTable(data []int) bool {
lookup := make(map[int]struct{}, 8)
for _, number := range data {
_, found := lookup[number]
if found {
return true
}
lookup[number] = struct{}{}
}
return false
}
func BenchmarkHasDuplicatesFrom1To7WithBits(b *testing.B) {
data := []int{1, 5, 2, 3, 6, 4, 7, 2, 7}
for i := 1; i < b.N; i++ {
_ = HasDuplicatesFrom1To7WithBits(data)
}
}
func BenchmarkHasDuplicatesFrom1To7WithArray(b *testing.B) {
data := []int{1, 5, 2, 3, 6, 4, 7, 2, 7}
for i := 1; i < b.N; i++ {
_ = HasDuplicatesFrom1To7WithArray(data)
}
}
func BenchmarkHasDuplicatesFrom1To7WithHashTable(b *testing.B) {
data := []int{1, 5, 2, 3, 6, 4, 7, 2, 7}
for i := 1; i < b.N; i++ {
_ = HasDuplicatesFrom1To7WithHashTable(data)
}
}

View File

@ -0,0 +1,19 @@
package main
import (
"fmt"
"unsafe"
)
func main() {
var number int32 = 0x12345678
pointer := unsafe.Pointer(&number)
fmt.Printf("0x")
for i := 0; i < 4; i++ {
byteValue := *(*int8)(unsafe.Add(pointer, i))
fmt.Printf("%x", byteValue)
}
fmt.Println()
}

View File

@ -0,0 +1,24 @@
package main
import (
"fmt"
"unsafe"
)
func IsLittleEndian() bool {
var number int16 = 0x0001
pointer := (*int8)(unsafe.Pointer(&number))
return *pointer == 1
}
func IsBigEndian() bool {
return !IsLittleEndian()
}
func main() {
if IsLittleEndian() {
fmt.Println("Little endian")
} else {
fmt.Println("Big endian")
}
}

View File

@ -0,0 +1,23 @@
package main
import (
"testing"
)
// go test -bench=. even_test.go
var result int
func BenchmarkEven1(b *testing.B) {
for i := 1; i < b.N; i++ {
result = i & 1
_ = result
}
}
func BenchmarkEven2(b *testing.B) {
for i := 1; i < b.N; i++ {
result = i % 2
_ = result
}
}

View File

@ -0,0 +1,15 @@
package main
import "fmt"
func main() {
var array = [...]int8{2, 3, 4, 2, 3, 1, 4}
var number int8
for _, element := range array {
fmt.Printf("%08b ^ %08b = %08b\n", number, element, number^element)
number ^= element
}
fmt.Printf("\nResult: %08b\n", number)
}

View File

@ -0,0 +1,20 @@
package main
import (
"fmt"
"math"
)
func main() {
var signed int8 = math.MaxInt8
signed++
var unsigned uint8 = math.MaxUint8
unsigned++
fmt.Println(signed)
fmt.Println(unsigned)
// var signed int8 = math.MaxInt8 + 1 -> compilation error
// var unsigned uint8 = math.MaxUint8 + 1 -> compilation error
}

View File

@ -0,0 +1,11 @@
package main
import "fmt"
func main() {
var x uint8 = 3
var y int8 = 3
fmt.Println(^x)
fmt.Println(^y)
}

View File

@ -0,0 +1,38 @@
package main
import (
"fmt"
"strconv"
"strings"
)
func Convert(address string) (uint32, error) {
const octetsCount = 4
segments := strings.Split(address, ".")
if len(segments) != octetsCount {
return 0, fmt.Errorf("invalid IPv4 address")
}
var result uint32 // also possible [4]byte
for idx := 0; idx < octetsCount; idx++ {
number, err := strconv.Atoi(segments[idx])
if err != nil {
return 0, err
}
if number < 0 || number > 255 {
return 0, fmt.Errorf("invalid IPv4 address")
}
bitOffset := (octetsCount - idx - 1) * 8
result |= uint32(number << bitOffset)
fmt.Printf("%08b = %d\n", number, number)
}
return result, nil
}
func main() {
address, _ := Convert("255.255.6.0")
fmt.Printf("Address: %b = %d\n", address, address)
}

View File

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

View File

@ -0,0 +1,52 @@
package main
import (
"errors"
"math"
)
var ErrIntOverflow = errors.New("integer overflow")
func Inc(counter int) (int, error) {
if counter == math.MaxInt {
return 0, ErrIntOverflow
}
return counter + 1, nil
}
func Add(lhs, rhs int) (int, error) {
if rhs > 0 {
if lhs > math.MaxInt-rhs {
return 0, ErrIntOverflow
}
} else if rhs < 0 {
if lhs < math.MinInt-rhs {
return 0, ErrIntOverflow
}
}
return lhs + rhs, nil
}
func Mul(lhs, rhs int) (int, error) {
if lhs == 0 || rhs == 0 {
return 0, nil
}
if lhs == 1 || rhs == 1 {
return lhs * rhs, nil
}
if (lhs == -1 && rhs == math.MinInt) || (rhs == -1 && lhs == math.MinInt) {
return 0, ErrIntOverflow
}
if lhs > math.MaxInt/rhs {
return 0, ErrIntOverflow
} else if lhs < math.MinInt/rhs {
return 0, ErrIntOverflow
}
return lhs * rhs, nil
}

View File

@ -0,0 +1,16 @@
package main
import "fmt"
func main() {
var value int32 = 100
var pointer *int32 = &value
fmt.Println("address:", pointer)
fmt.Println("value:", *pointer)
*pointer = 500
fmt.Println("address:", pointer)
fmt.Println("value:", *pointer)
}

View File

@ -0,0 +1,21 @@
package main
import "fmt"
func process(temp **int32) {
var value2 int32 = 200
*temp = &value2
}
func main() {
var value1 int32 = 100
pointer := &value1
fmt.Println("value:", *pointer)
fmt.Println("address:", pointer)
process(&pointer)
fmt.Println("value", *pointer)
fmt.Println("address:", pointer)
}

View File

@ -0,0 +1,21 @@
package main
import "fmt"
func process(temp *int32) {
var value2 int32 = 200
temp = &value2
}
func main() {
var value1 int32 = 100
pointer := &value1
fmt.Println("value:", *pointer)
fmt.Println("adress:", pointer)
process(pointer)
fmt.Println("value:", *pointer)
fmt.Println("adress:", pointer)
}

View File

@ -0,0 +1,17 @@
package main
import "fmt"
// Need to show solution
func double(number int) {
fmt.Println("address:", &number)
number *= 2
}
func main() {
number := 100
double(number)
fmt.Println("number: ", number)
fmt.Println("address:", &number)
}

View File

@ -0,0 +1,17 @@
package main
// 0000 0000 = 0
// 0000 0001 = 1
// 0000 0010 = 2
// 0000 0100 = 4
// 0000 1000 = 8
// 0001 0000 = 16
// 0010 0000 = 32
// 0100 0000 = 64
// 1000 0000 = 128
// 0000 1111
func IsPowerOfTwo(value int) bool {
return value > 0 && value&(value-1) == 0
}

View File

@ -0,0 +1,26 @@
package main
import (
"runtime"
"unsafe"
)
// go run main.go
// go run -gcflags=-d=checkptr main.go
func main() {
x := new(int)
y := new(int)
ptrX := unsafe.Pointer(x)
addressY := uintptr(unsafe.Pointer(y))
// arithmetic operation
_ = addressY + 2
_ = addressY - 2
runtime.GC()
*(*int)(ptrX) = 100
*(*int)(unsafe.Pointer(addressY)) = 300 // dangerous
}

View File

@ -0,0 +1,27 @@
package main
import (
"fmt"
"unsafe"
)
// go run main.go
// go run -gcflags=-d=checkptr main.go
//go:noinline
func allocation(index int) byte {
var data [1 << 20]byte
return data[index]
}
func main() {
var array [10]int
address1 := (uintptr)(unsafe.Pointer(&array))
fmt.Println("address1:", address1)
allocation(100)
address2 := (uintptr)(unsafe.Pointer(&array))
fmt.Println("address2:", address2)
fmt.Println("address1:", address1)
}

View File

@ -0,0 +1,20 @@
package main
import (
"fmt"
"unsafe"
)
func main() {
var (
x, y int = 1, 2
)
p1 := unsafe.Pointer(&x)
p2 := unsafe.Add(p1, 8)
fmt.Println("p1: ", *(*int)(p1))
fmt.Println("p2: ", *(*int)(p2))
_ = y
}

View File

@ -0,0 +1,20 @@
package main
import (
"fmt"
"unsafe"
)
func main() {
var value uint32 = 0xFFFFFFFF
pointer := unsafe.Pointer(&value)
bytePointer := (*uint8)(pointer)
fmt.Println("value1:", *bytePointer)
pointer = unsafe.Add(pointer, 2)
twoBytePointer := (*uint16)(pointer)
fmt.Println("value2:", *twoBytePointer)
}

View File

@ -0,0 +1,14 @@
package main
import (
"fmt"
"unsafe"
)
func main() {
var value1 int8 = 10
fmt.Println("size1:", unsafe.Sizeof(value1)) // compile time
var value2 int32 = 10
fmt.Println("size2:", unsafe.Sizeof(value2)) // compile time
}

View File

@ -0,0 +1,12 @@
package main
import "fmt"
func init() {
fmt.Println("init[main.go] called")
}
func main() {
fmt.Println("main called")
secondary()
}

View File

@ -0,0 +1,11 @@
package main
import "fmt"
func init() {
fmt.Println("init[secondary.go] called")
}
func secondary() {
fmt.Println("secondary called")
}

View File

@ -0,0 +1,15 @@
package main
import (
"fmt"
"golang_course/environment/init_in_any_packages/secondary"
)
func init() {
fmt.Println("init[main.go] called")
}
func main() {
fmt.Println("main called")
secondary.Secondary()
}

View File

@ -0,0 +1,11 @@
package secondary
import "fmt"
func init() {
fmt.Println("init[secondary.go] called")
}
func Secondary() {
fmt.Println("secondary called")
}

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