Исходники и презентации
This commit is contained in:
19
lessons/structs/alignment_functions/main.go
Normal file
19
lessons/structs/alignment_functions/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type data struct {
|
||||
aaa bool
|
||||
bbb int32
|
||||
ccc bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
d := data{}
|
||||
fmt.Println(unsafe.Offsetof(d.ccc))
|
||||
|
||||
fmt.Println(unsafe.Alignof(d))
|
||||
}
|
||||
30
lessons/structs/ambiguous_selectors/main.go
Normal file
30
lessons/structs/ambiguous_selectors/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
type Derived1 struct {
|
||||
values []int
|
||||
}
|
||||
|
||||
func (d Derived1) Print() {}
|
||||
|
||||
type Derived2 struct {
|
||||
values []int
|
||||
}
|
||||
|
||||
func (d Derived2) Print() {}
|
||||
|
||||
type Base struct {
|
||||
Derived1
|
||||
Derived2
|
||||
}
|
||||
|
||||
func main() {
|
||||
var base Base
|
||||
// _ = base.values
|
||||
// base.Print()
|
||||
|
||||
base.Derived1.values = nil
|
||||
base.Derived2.values = nil
|
||||
|
||||
base.Derived1.Print()
|
||||
base.Derived2.Print()
|
||||
}
|
||||
22
lessons/structs/anonymous_struct/main.go
Normal file
22
lessons/structs/anonymous_struct/main.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
var book = struct {
|
||||
author struct {
|
||||
name string
|
||||
surname string
|
||||
}
|
||||
title string
|
||||
}{
|
||||
author: struct {
|
||||
name string
|
||||
surname string
|
||||
}{
|
||||
name: "Name",
|
||||
surname: "Surname",
|
||||
},
|
||||
title: "Title",
|
||||
}
|
||||
|
||||
_ = book
|
||||
}
|
||||
33
lessons/structs/bind_receiver/main.go
Normal file
33
lessons/structs/bind_receiver/main.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Data struct {
|
||||
value int
|
||||
}
|
||||
|
||||
func (d Data) Value1() int {
|
||||
return d.value
|
||||
}
|
||||
|
||||
func (d *Data) Value2() int {
|
||||
return d.value
|
||||
}
|
||||
|
||||
func main() {
|
||||
data := Data{100}
|
||||
pointer := &data
|
||||
|
||||
value1ByData := data.Value1
|
||||
value1ByPointer := pointer.Value1
|
||||
|
||||
value2ByData := data.Value2
|
||||
value2ByPointer := pointer.Value2
|
||||
|
||||
data.value = 200
|
||||
|
||||
fmt.Println("value1ByData:", value1ByData())
|
||||
fmt.Println("value1ByPointer:", value1ByPointer())
|
||||
fmt.Println("value2ByData:", value2ByData())
|
||||
fmt.Println("value2ByPointer:", value2ByPointer())
|
||||
}
|
||||
9
lessons/structs/blank_methods/main.go
Normal file
9
lessons/structs/blank_methods/main.go
Normal file
@ -0,0 +1,9 @@
|
||||
package main
|
||||
|
||||
type Data struct{}
|
||||
|
||||
func (d Data) _() {}
|
||||
func (d Data) _() {}
|
||||
func (d Data) _() {}
|
||||
func (d Data) _() {}
|
||||
func (d Data) _() {}
|
||||
15
lessons/structs/check_struct_size/main.go
Normal file
15
lessons/structs/check_struct_size/main.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type Data struct {
|
||||
id int32
|
||||
data [60]byte
|
||||
}
|
||||
|
||||
// Describe:
|
||||
// - Alignof
|
||||
// - Offsetof
|
||||
|
||||
var _ uintptr = unsafe.Sizeof(Data{}) - 64
|
||||
var _ uintptr = 64 - unsafe.Sizeof(Data{})
|
||||
40
lessons/structs/closer/main.go
Normal file
40
lessons/structs/closer/main.go
Normal file
@ -0,0 +1,40 @@
|
||||
package main
|
||||
|
||||
type Closer struct {
|
||||
actios []func()
|
||||
}
|
||||
|
||||
func (c *Closer) Add(action func()) {
|
||||
if action != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.actios = append(c.actios, action)
|
||||
}
|
||||
|
||||
func (c *Closer) Close() {
|
||||
for _, action := range c.actios {
|
||||
action()
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// code..
|
||||
var closer Closer
|
||||
|
||||
closer.Add(func() {
|
||||
// close connections
|
||||
})
|
||||
|
||||
closer.Add(func() {
|
||||
// close database
|
||||
})
|
||||
|
||||
closer.Add(func() {
|
||||
// close worker
|
||||
})
|
||||
|
||||
// code...
|
||||
|
||||
closer.Close()
|
||||
}
|
||||
20
lessons/structs/comparison/main.go
Normal file
20
lessons/structs/comparison/main.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type client struct {
|
||||
id string
|
||||
operations []float64
|
||||
}
|
||||
|
||||
func main() {
|
||||
client1 := client{id: "x", operations: []float64{1.}}
|
||||
client2 := client{id: "y", operations: []float64{1.}}
|
||||
fmt.Println(client1 == client2)
|
||||
|
||||
/*
|
||||
var anyClient1 any = client{id: "x", operations: []float64{1.}}
|
||||
var anyClient2 any = client{id: "y", operations: []float64{1.}}
|
||||
fmt.Println(anyClient1 == anyClient2)
|
||||
*/
|
||||
}
|
||||
33
lessons/structs/comparison_benchmark/comparison_test.go
Normal file
33
lessons/structs/comparison_benchmark/comparison_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// go test -bench=. comparison_test.go
|
||||
|
||||
type Data1 struct {
|
||||
size int32
|
||||
values [10 << 20]byte
|
||||
}
|
||||
|
||||
type Data2 struct {
|
||||
values [10 << 20]byte
|
||||
size int32
|
||||
}
|
||||
|
||||
func BenchmarkComparisonData1(b *testing.B) {
|
||||
data1 := Data1{size: 100}
|
||||
data2 := Data1{size: 101}
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = data1 == data2
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkComparisonData2(b *testing.B) {
|
||||
data1 := Data2{size: 100}
|
||||
data2 := Data2{size: 101}
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = data1 == data2
|
||||
}
|
||||
}
|
||||
30
lessons/structs/configurable_object/main.go
Normal file
30
lessons/structs/configurable_object/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
type Logger struct {
|
||||
name string
|
||||
level string
|
||||
}
|
||||
|
||||
func NewLogger() *Logger {
|
||||
return &Logger{}
|
||||
}
|
||||
|
||||
func (l *Logger) WithName(name string) *Logger {
|
||||
l.name = name
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logger) WithLevel(level string) *Logger {
|
||||
l.level = level
|
||||
return l
|
||||
}
|
||||
|
||||
func main() {
|
||||
logger1 := NewLogger()
|
||||
logger2 := NewLogger().WithLevel("INFO")
|
||||
logger3 := NewLogger().WithName("storage")
|
||||
|
||||
_ = logger1
|
||||
_ = logger2
|
||||
_ = logger3
|
||||
}
|
||||
19
lessons/structs/copy_struct/main.go
Normal file
19
lessons/structs/copy_struct/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
type Data struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 1 way
|
||||
data1 := Data{x: 10, y: 10}
|
||||
temp1 := data1
|
||||
_ = temp1
|
||||
|
||||
// 2 way
|
||||
data2 := Data{x: 10, y: 10}
|
||||
var temp2 Data
|
||||
temp2.x = data2.x
|
||||
temp2.y = data2.y
|
||||
}
|
||||
30
lessons/structs/defer_calculating_1/main.go
Normal file
30
lessons/structs/defer_calculating_1/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type data1 struct {
|
||||
value int
|
||||
}
|
||||
|
||||
func (d data1) print() {
|
||||
fmt.Println("data1", d.value)
|
||||
}
|
||||
|
||||
type data2 struct {
|
||||
value int
|
||||
}
|
||||
|
||||
func (d *data2) print() {
|
||||
fmt.Println("data2", d.value)
|
||||
}
|
||||
|
||||
func main() {
|
||||
d1 := data1{}
|
||||
defer d1.print()
|
||||
|
||||
d2 := data2{}
|
||||
defer d2.print()
|
||||
|
||||
d1.value = 100
|
||||
d2.value = 200
|
||||
}
|
||||
22
lessons/structs/defer_calculating_2/main.go
Normal file
22
lessons/structs/defer_calculating_2/main.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
type Data struct{}
|
||||
|
||||
func MakeData(pointer *int) Data {
|
||||
println("MakeData:", *pointer)
|
||||
return Data{}
|
||||
}
|
||||
|
||||
func (Data) Print(pointer *int) {
|
||||
println("Print:", *pointer)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var value = 1
|
||||
var pointer = &value
|
||||
defer MakeData(pointer).Print(pointer)
|
||||
|
||||
value = 2
|
||||
pointer = new(int)
|
||||
MakeData(pointer)
|
||||
}
|
||||
30
lessons/structs/different_receivers/main.go
Normal file
30
lessons/structs/different_receivers/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type customer1 struct {
|
||||
balance int
|
||||
}
|
||||
|
||||
func (c customer1) add(value int) {
|
||||
c.balance += value
|
||||
}
|
||||
|
||||
type customer2 struct {
|
||||
balance int
|
||||
}
|
||||
|
||||
func (c *customer2) add(value int) {
|
||||
c.balance += value
|
||||
}
|
||||
|
||||
func main() {
|
||||
c1 := customer1{}
|
||||
c1.add(100)
|
||||
|
||||
c2 := customer2{}
|
||||
c2.add(100)
|
||||
|
||||
fmt.Println(c1)
|
||||
fmt.Println(c2)
|
||||
}
|
||||
107
lessons/structs/dod/comparison_test.go
Normal file
107
lessons/structs/dod/comparison_test.go
Normal file
@ -0,0 +1,107 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// go test -bench=. comparison_test.go
|
||||
|
||||
type OODStyle struct {
|
||||
Field1 int
|
||||
Field2 string
|
||||
Field3 int
|
||||
Field4 string
|
||||
Field5 int
|
||||
Field6 string
|
||||
Field7 int
|
||||
Field8 string
|
||||
}
|
||||
|
||||
type DODStyle struct {
|
||||
Field1 []int
|
||||
Field2 []string
|
||||
Field3 []int
|
||||
Field4 []string
|
||||
Field5 []int
|
||||
Field6 []string
|
||||
Field7 []int
|
||||
Field8 []string
|
||||
}
|
||||
|
||||
var Sink int
|
||||
|
||||
func BenchmarkDOD(b *testing.B) {
|
||||
r := rand.New(rand.NewSource(42))
|
||||
data := generateDOD(r, 1_000_000)
|
||||
b.ResetTimer()
|
||||
|
||||
Sink = 0
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j, f1 := range data.Field1 {
|
||||
if f1 == 500000 {
|
||||
Sink = j
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkOOD(b *testing.B) {
|
||||
r := rand.New(rand.NewSource(42))
|
||||
data := generateOOD(r, 1_000_000)
|
||||
b.ResetTimer()
|
||||
|
||||
Sink = 0
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j, ant := range data {
|
||||
if ant.Field1 == 500000 {
|
||||
Sink = j
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateOOD(r *rand.Rand, size int) []OODStyle {
|
||||
data := make([]OODStyle, size)
|
||||
for i := range data {
|
||||
data[i] = OODStyle{
|
||||
Field1: r.Intn(1000),
|
||||
Field2: fmt.Sprintf("field2-%d", r.Intn(1000)),
|
||||
Field3: r.Intn(1000),
|
||||
Field4: fmt.Sprintf("field4-%d", r.Intn(1000)),
|
||||
Field5: r.Intn(1000),
|
||||
Field6: fmt.Sprintf("field6-%d", r.Intn(1000)),
|
||||
Field7: r.Intn(1000),
|
||||
Field8: fmt.Sprintf("fiel8-%d", r.Intn(1000)),
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func generateDOD(r *rand.Rand, size int) DODStyle {
|
||||
data := DODStyle{
|
||||
Field1: make([]int, size),
|
||||
Field2: make([]string, size),
|
||||
Field3: make([]int, size),
|
||||
Field4: make([]string, size),
|
||||
Field5: make([]int, size),
|
||||
Field6: make([]string, size),
|
||||
Field7: make([]int, size),
|
||||
Field8: make([]string, size),
|
||||
}
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
data.Field1[i] = r.Intn(1000)
|
||||
data.Field2[i] = fmt.Sprintf("field2-%d", r.Intn(1000))
|
||||
data.Field3[i] = r.Intn(1000)
|
||||
data.Field4[i] = fmt.Sprintf("field4-%d", r.Intn(1000))
|
||||
data.Field5[i] = r.Intn(1000)
|
||||
data.Field6[i] = fmt.Sprintf("field6-%d", r.Intn(1000))
|
||||
data.Field7[i] = r.Intn(1000)
|
||||
data.Field8[i] = fmt.Sprintf("fiel8-%d", r.Intn(1000))
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
16
lessons/structs/empty_struct_size/main.go
Normal file
16
lessons/structs/empty_struct_size/main.go
Normal file
@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type data struct{}
|
||||
|
||||
func main() {
|
||||
x := &data{}
|
||||
y := data{}
|
||||
|
||||
fmt.Println(unsafe.Sizeof(x))
|
||||
fmt.Println(unsafe.Sizeof(y))
|
||||
}
|
||||
20
lessons/structs/empty_structs/main.go
Normal file
20
lessons/structs/empty_structs/main.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type empty struct{}
|
||||
|
||||
func main() {
|
||||
a := struct{}{}
|
||||
b := struct{}{}
|
||||
c := empty{}
|
||||
d := [0]byte{}
|
||||
|
||||
fmt.Println(unsafe.Pointer(&a))
|
||||
fmt.Println(unsafe.Pointer(&b))
|
||||
fmt.Println(unsafe.Pointer(&c))
|
||||
fmt.Println(unsafe.Pointer(&d))
|
||||
}
|
||||
42
lessons/structs/empty_structs_internal/main.go
Normal file
42
lessons/structs/empty_structs_internal/main.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import "time"
|
||||
|
||||
func fn() {
|
||||
var v3 int
|
||||
var e3 struct{}
|
||||
|
||||
println("v3:", &v3)
|
||||
println("e3:", &e3)
|
||||
}
|
||||
|
||||
func main() {
|
||||
var v1 int
|
||||
var e1 struct{}
|
||||
var v2 int
|
||||
var e2 struct{}
|
||||
|
||||
println("v1:", &v1)
|
||||
println("e1:", &e1)
|
||||
println("v2:", &v2)
|
||||
println("e2:", &e2)
|
||||
|
||||
fn()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
go func() {
|
||||
var gv1 int
|
||||
var ge1 struct{}
|
||||
var gv2 int
|
||||
var ge2 struct{}
|
||||
|
||||
println()
|
||||
println("gv1:", &gv1)
|
||||
println("ge1:", &ge1)
|
||||
println("gv2:", &gv2)
|
||||
println("ge2:", &ge2)
|
||||
}()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
32
lessons/structs/final_zero_field/main.go
Normal file
32
lessons/structs/final_zero_field/main.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func main() {
|
||||
type T1 struct {
|
||||
a struct{}
|
||||
x int64
|
||||
}
|
||||
|
||||
var t1 T1
|
||||
fmt.Println("size:", unsafe.Sizeof(t1))
|
||||
/*
|
||||
fmt.Println("address a:", unsafe.Pointer(&t1.a))
|
||||
fmt.Println("address x:", unsafe.Pointer(&t1.x))
|
||||
*/
|
||||
|
||||
type T2 struct {
|
||||
x int64
|
||||
a struct{}
|
||||
}
|
||||
|
||||
var t2 T2
|
||||
fmt.Println("size:", unsafe.Sizeof(t2))
|
||||
/*
|
||||
fmt.Println("address a:", unsafe.Pointer(&t2.a))
|
||||
fmt.Println("address x:", unsafe.Pointer(&t2.x))
|
||||
*/
|
||||
}
|
||||
50
lessons/structs/functional_options/main.go
Normal file
50
lessons/structs/functional_options/main.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
type Option func(*User)
|
||||
|
||||
func WithEmail(email string) Option {
|
||||
return func(user *User) {
|
||||
user.Email = email
|
||||
}
|
||||
}
|
||||
|
||||
func WithPhone(phone string) Option {
|
||||
return func(user *User) {
|
||||
user.Phone = phone
|
||||
}
|
||||
}
|
||||
|
||||
func WithAddress(address string) Option {
|
||||
return func(user *User) {
|
||||
user.Address = address
|
||||
}
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Surname string
|
||||
Email string
|
||||
Phone string
|
||||
Address string
|
||||
}
|
||||
|
||||
func NewUser(name string, surname string, options ...Option) User {
|
||||
user := User{
|
||||
Name: name,
|
||||
Surname: surname,
|
||||
}
|
||||
|
||||
for _, option := range options {
|
||||
option(&user)
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
func main() {
|
||||
user1 := NewUser("Ivan", "Ivanov", WithEmail("ivanov@yandex.ru"))
|
||||
user2 := NewUser("Petr", "Petrov", WithEmail("petrov@yandex.ru"), WithPhone("+67453"))
|
||||
|
||||
_ = user1
|
||||
_ = user2
|
||||
}
|
||||
19
lessons/structs/implicit_method_call/main.go
Normal file
19
lessons/structs/implicit_method_call/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Data struct{}
|
||||
|
||||
func (d Data) Print() {
|
||||
fmt.Println("data")
|
||||
}
|
||||
|
||||
func main() {
|
||||
var data Data
|
||||
|
||||
data.Print()
|
||||
(&data).Print()
|
||||
|
||||
(Data).Print(data)
|
||||
(*Data).Print(&data)
|
||||
}
|
||||
30
lessons/structs/inheritance/main.go
Normal file
30
lessons/structs/inheritance/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Person struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (p *Person) Intro() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
type Woman struct {
|
||||
Person
|
||||
}
|
||||
|
||||
func (w *Woman) Intro() string {
|
||||
return "Mrs. " + w.Person.Intro()
|
||||
}
|
||||
|
||||
func main() {
|
||||
woman := Woman{
|
||||
Person: Person{
|
||||
Name: "Ekaterina",
|
||||
},
|
||||
}
|
||||
|
||||
fmt.Println(woman.Intro())
|
||||
fmt.Println(woman.Person.Intro())
|
||||
}
|
||||
28
lessons/structs/methods_for_basic_types/main.go
Normal file
28
lessons/structs/methods_for_basic_types/main.go
Normal file
@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
type Age int
|
||||
|
||||
func (age Age) LargerThan(other Age) bool {
|
||||
return age > other
|
||||
}
|
||||
|
||||
type FilterFunc func(int) bool
|
||||
|
||||
func (ff FilterFunc) Filter(value int) bool {
|
||||
return ff(value)
|
||||
}
|
||||
|
||||
type StringSet map[string]struct{}
|
||||
|
||||
func (ss StringSet) Has(key string) bool {
|
||||
_, found := ss[key]
|
||||
return found
|
||||
}
|
||||
|
||||
func (ss StringSet) Add(key string) {
|
||||
ss[key] = struct{}{}
|
||||
}
|
||||
|
||||
func (ss StringSet) Remove(key string) {
|
||||
delete(ss, key)
|
||||
}
|
||||
29
lessons/structs/methods_with_types/main.go
Normal file
29
lessons/structs/methods_with_types/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "io"
|
||||
|
||||
type (
|
||||
IntAlias = int
|
||||
IntType int
|
||||
)
|
||||
|
||||
func (i int) Do() {} // compilation error: basic type
|
||||
func (i IntAlias) Do() {} // compilation error: basic type
|
||||
func (i IntType) Do() {} // ok
|
||||
|
||||
type (
|
||||
IntPtrAlias = *int
|
||||
IntPtrType *int
|
||||
)
|
||||
|
||||
func (i IntPtrAlias) Do() {} // compilation error: pointer
|
||||
func (i IntPtrType) Do() {} // compilation error: pointer
|
||||
|
||||
type (
|
||||
CloserAlias = io.Closer
|
||||
CloserType io.Closer
|
||||
)
|
||||
|
||||
func (i io.Closer) Do() {} // compilation error: interface
|
||||
func (i CloserAlias) Do() {} // compilation error: interface
|
||||
func (i CloserType) Do() {} // compilation error: interface
|
||||
18
lessons/structs/nil_receiver/main.go
Normal file
18
lessons/structs/nil_receiver/main.go
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Obect struct{}
|
||||
|
||||
func (o *Obect) Print() {
|
||||
if o == nil {
|
||||
fmt.Println("nil")
|
||||
} else {
|
||||
fmt.Println("not nil")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var object *Obect
|
||||
object.Print()
|
||||
}
|
||||
29
lessons/structs/optional_parameters/main.go
Normal file
29
lessons/structs/optional_parameters/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
type Option func(*User)
|
||||
|
||||
type User struct {
|
||||
Name string
|
||||
Surname string
|
||||
Email *string
|
||||
Phone *string
|
||||
Address *string
|
||||
}
|
||||
|
||||
func NewUser(name string, surname string, email, phone, address *string) User {
|
||||
return User{
|
||||
Name: name,
|
||||
Surname: surname,
|
||||
Email: email,
|
||||
Phone: phone,
|
||||
Address: address,
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
email := "test@test.ru"
|
||||
phone := ""
|
||||
|
||||
user1 := NewUser("Ivan", "Ivanov", &email, &phone, nil)
|
||||
_ = user1
|
||||
}
|
||||
24
lessons/structs/recursive_receiver/main.go
Normal file
24
lessons/structs/recursive_receiver/main.go
Normal file
@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type account struct {
|
||||
balance int
|
||||
}
|
||||
|
||||
type client struct {
|
||||
account *account
|
||||
}
|
||||
|
||||
func (c client) add(value int) {
|
||||
c.account.balance += value
|
||||
}
|
||||
|
||||
func main() {
|
||||
c := client{
|
||||
account: &account{},
|
||||
}
|
||||
|
||||
c.add(100)
|
||||
fmt.Println(c.account.balance)
|
||||
}
|
||||
28
lessons/structs/skipping_selectors/main.go
Normal file
28
lessons/structs/skipping_selectors/main.go
Normal file
@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
type A struct {
|
||||
value int
|
||||
}
|
||||
|
||||
func (a A) Print() {}
|
||||
|
||||
type B struct {
|
||||
A
|
||||
}
|
||||
|
||||
type C struct {
|
||||
*B
|
||||
}
|
||||
|
||||
func main() {
|
||||
var c C = C{B: &B{A: A{value: 10}}}
|
||||
//var c C = C{&B{A{10}}} -> the same
|
||||
|
||||
_ = c.B.A.value
|
||||
_ = c.A.value
|
||||
_ = c.value
|
||||
|
||||
c.B.A.Print()
|
||||
c.B.Print()
|
||||
c.Print()
|
||||
}
|
||||
16
lessons/structs/struct/main.go
Normal file
16
lessons/structs/struct/main.go
Normal file
@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
type Data struct {
|
||||
x int
|
||||
y int
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 1 way
|
||||
data1 := Data{10, 20}
|
||||
_ = data1
|
||||
|
||||
// 2 way
|
||||
data2 := Data{x: 10, y: 20}
|
||||
_ = data2
|
||||
}
|
||||
34
lessons/structs/struct_alignment_1/main.go
Normal file
34
lessons/structs/struct_alignment_1/main.go
Normal file
@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type data1 struct {
|
||||
aaa bool
|
||||
bbb int32
|
||||
ccc bool
|
||||
}
|
||||
|
||||
type data2 struct {
|
||||
aaa int32
|
||||
bbb bool
|
||||
ccc bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(unsafe.Sizeof(data1{}))
|
||||
fmt.Println(unsafe.Sizeof(data2{}))
|
||||
|
||||
/*
|
||||
d := data1{
|
||||
aaa: true,
|
||||
bbb: 5,
|
||||
ccc: true,
|
||||
}
|
||||
|
||||
b := (*[12]byte)(unsafe.Pointer(&d))
|
||||
fmt.Printf("Bytes are %#v\n", b)
|
||||
*/
|
||||
}
|
||||
18
lessons/structs/struct_alignment_2/main.go
Normal file
18
lessons/structs/struct_alignment_2/main.go
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type data1 struct {
|
||||
aaa bool
|
||||
bbb [1023]byte
|
||||
ccc bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
d := data1{}
|
||||
fmt.Println(unsafe.Sizeof(d))
|
||||
fmt.Println(unsafe.Alignof(d))
|
||||
}
|
||||
12
lessons/structs/struct_inside_function/main.go
Normal file
12
lessons/structs/struct_inside_function/main.go
Normal file
@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
func HandleRequest() {
|
||||
type request struct {
|
||||
name string
|
||||
surname string
|
||||
balance float32
|
||||
}
|
||||
|
||||
var req request
|
||||
_ = req
|
||||
}
|
||||
19
lessons/structs/stuct_sugar/main.go
Normal file
19
lessons/structs/stuct_sugar/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
type Data struct {
|
||||
}
|
||||
|
||||
func (d Data) Print() {}
|
||||
|
||||
func main() {
|
||||
var value1 = Data{}
|
||||
value1.Print()
|
||||
|
||||
// 1 way
|
||||
var value2WithSugar = &Data{}
|
||||
value2WithSugar.Print()
|
||||
|
||||
// 2 way
|
||||
var value2WithoutSugar = new(Data)
|
||||
(*value2WithoutSugar).Print()
|
||||
}
|
||||
17
lessons/structs/type_alias_and_definition/main.go
Normal file
17
lessons/structs/type_alias_and_definition/main.go
Normal file
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
type (
|
||||
A = int
|
||||
B int
|
||||
)
|
||||
|
||||
func main() {
|
||||
var a A = 1
|
||||
var b B = 2
|
||||
|
||||
var ia int = a
|
||||
_ = ia
|
||||
|
||||
var ib int = int(b)
|
||||
_ = ib
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Data struct {
|
||||
}
|
||||
|
||||
func (d Data) Print() {
|
||||
fmt.Println("data")
|
||||
}
|
||||
|
||||
type (
|
||||
DataType Data
|
||||
DataAlias = Data
|
||||
)
|
||||
|
||||
func main() {
|
||||
data1 := DataType{}
|
||||
data1.Print() // compilation error
|
||||
|
||||
data2 := DataAlias{}
|
||||
data2.Print()
|
||||
}
|
||||
29
lessons/structs/type_embedding_correct/main.go
Normal file
29
lessons/structs/type_embedding_correct/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "io"
|
||||
|
||||
type LoggerV1 struct {
|
||||
closer io.WriteCloser
|
||||
}
|
||||
|
||||
func (l *LoggerV1) Write(data []byte) (int, error) {
|
||||
return l.closer.Write(data)
|
||||
}
|
||||
|
||||
func (l *LoggerV1) Close() error {
|
||||
return l.closer.Close()
|
||||
}
|
||||
|
||||
type LoggerV2 struct {
|
||||
io.WriteCloser
|
||||
}
|
||||
|
||||
func main() {
|
||||
v1 := LoggerV1{}
|
||||
v1.Write(nil)
|
||||
v1.Close()
|
||||
|
||||
v2 := LoggerV2{}
|
||||
v2.Write(nil)
|
||||
v2.Close()
|
||||
}
|
||||
30
lessons/structs/type_embedding_incorrect/main.go
Normal file
30
lessons/structs/type_embedding_incorrect/main.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import "sync"
|
||||
|
||||
type Storage struct {
|
||||
sync.Mutex
|
||||
data map[string]string
|
||||
}
|
||||
|
||||
func NewStorage() *Storage {
|
||||
return &Storage{
|
||||
data: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Storage) Get(key string) (string, bool) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
value, found := s.data[key]
|
||||
return value, found
|
||||
}
|
||||
|
||||
func main() {
|
||||
storage := NewStorage()
|
||||
storage.Get("key_1")
|
||||
|
||||
storage.Lock() // dangerous
|
||||
storage.Unlock() // dangerous
|
||||
}
|
||||
22
lessons/structs/union_1/main.go
Normal file
22
lessons/structs/union_1/main.go
Normal file
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// SBO (Small Buffer Optimization)
|
||||
type SBO struct {
|
||||
size int64
|
||||
union [16]byte // 8B[pointer]8B[capacity]
|
||||
}
|
||||
|
||||
func main() {
|
||||
var small SBO
|
||||
small.size = 10
|
||||
small.union = [16]byte{}
|
||||
|
||||
var big SBO
|
||||
big.size = 1024
|
||||
pointer := (*[2048]byte)(unsafe.Pointer(&big.union))
|
||||
*pointer = [2048]byte{}
|
||||
capacity := (*int64)(unsafe.Add(unsafe.Pointer(&big.union), 8))
|
||||
*capacity = 2048
|
||||
}
|
||||
1
lessons/structs/union_2/main.go
Normal file
1
lessons/structs/union_2/main.go
Normal file
@ -0,0 +1 @@
|
||||
package main
|
||||
29
lessons/structs/unsafe_cast/performance_test.go
Normal file
29
lessons/structs/unsafe_cast/performance_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// go test -bench=. -benchmem performance_test.go
|
||||
|
||||
type Int int
|
||||
|
||||
var convertedData []int
|
||||
|
||||
func BenchmarkCast(b *testing.B) {
|
||||
data := make([]Int, 1024)
|
||||
for i := 0; i < b.N; i++ {
|
||||
convertedData = make([]int, 1024)
|
||||
for idx, value := range data {
|
||||
convertedData[idx] = int(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUnsafeCast(b *testing.B) {
|
||||
data := make([]Int, 1024)
|
||||
for i := 0; i < b.N; i++ {
|
||||
convertedData = *(*[]int)(unsafe.Pointer(&data))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user