Compare commits

...

5 Commits

Author SHA1 Message Date
lbenedar
589d2ae3d8 add ch14 2026-02-23 16:56:00 +03:00
lbenedar
1f4ba997b7 add ch13 2026-02-23 15:00:41 +03:00
lbenedar
b1935a4057 add ch12_3 2026-02-21 16:25:56 +03:00
lbenedar
cb314c36a9 add ch12_2 2026-02-21 15:17:10 +03:00
lbenedar
e66d76ddc9 add changes to ch12_1 2026-02-21 14:41:54 +03:00
18 changed files with 423 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.exe

39
ch12/1/ch12_1.go Normal file
View File

@@ -0,0 +1,39 @@
package main
import (
"fmt"
"math/rand"
)
func PrintNumbers() {
const IN_CHAN_NUM = 2
numCh := make(chan int, 20)
completeCh := make(chan int)
defer close(numCh)
defer close(completeCh)
for i := 0; i < IN_CHAN_NUM; i++ {
go func() {
for j := 0; j < 10; j++ {
numCh <- (rand.Int() % 100)
}
}()
}
go func() {
i := 0
for num := range numCh {
fmt.Println(num)
i++
if i == 20 {
break
}
}
completeCh <- 1
}()
select {
case <-completeCh:
}
}
func main() {
PrintNumbers()
}

44
ch12/2/ch12_2.go Normal file
View File

@@ -0,0 +1,44 @@
package main
import (
"fmt"
"math/rand"
)
func PrintNumbers() {
const chNum = 2
firstCh := make(chan int, 10)
secondCh := make(chan int, 20)
defer close(firstCh)
defer close(secondCh)
go func() {
for j := 0; j < 10; j++ {
firstCh <- (rand.Int() % 100)
}
}()
go func() {
for j := 0; j < 10; j++ {
secondCh <- (rand.Int() % 100)
}
}()
i := 0
forLoop:
for {
select {
case val1 := <-firstCh:
fmt.Printf("(%d) From first channel: %d\n", i+1, val1)
case val2 := <-secondCh:
fmt.Printf("(%d) From second channel: %d\n", i+1, val2)
}
i++
if i == chNum*10 {
break forLoop
}
}
}
func main() {
PrintNumbers()
}

3
ch12/2/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch12/2
go 1.25.0

28
ch12/3/ch12_3.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"fmt"
"math"
"sync"
)
func CreateSqrtMap() map[int]float64 {
numKeys := 100_000
newMap := make(map[int]float64)
for i := range numKeys {
newMap[i] = math.Sqrt(float64(i))
}
return newMap
}
var initCreateMapSqrt func() map[int]float64 = sync.OnceValue(CreateSqrtMap)
func main() {
sqrtMap := initCreateMapSqrt()
n := 100_000 / 1_000
for i := range n {
keyVal := i * 1_000
fmt.Printf("Value of map by key[%d]: %f\n", keyVal, sqrtMap[keyVal])
}
}

3
ch12/3/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch12/3
go 1.25.0

28
ch13/1/ch13_1.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"net/http"
"time"
)
type TimeHandler struct{}
func (th TimeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(time.Now().Format(time.RFC3339)))
}
func main() {
server := http.Server{
Addr: ":10100",
ReadTimeout: 30 * time.Second,
WriteTimeout: 90 * time.Second,
IdleTimeout: 120 * time.Second,
Handler: TimeHandler{},
}
err := server.ListenAndServe()
if err != nil {
if err != http.ErrServerClosed {
panic(err)
}
}
}

3
ch13/1/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch13/1
go 1.25.0

46
ch13/2/ch13_2.go Normal file
View File

@@ -0,0 +1,46 @@
package main
import (
"fmt"
"log/slog"
"net"
"net/http"
"time"
)
type TimeHandler struct{}
func (th TimeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(time.Now().Format(time.RFC3339)))
}
func RequestToIP(r *http.Request) string {
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
slog.Error(fmt.Sprintf("Wrong format of address: %q", r.RemoteAddr))
}
return ip
}
func RequestIPHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
slog.Info(RequestToIP(r))
h.ServeHTTP(w, r)
})
}
func main() {
server := http.Server{
Addr: ":10100",
ReadTimeout: 30 * time.Second,
WriteTimeout: 90 * time.Second,
IdleTimeout: 120 * time.Second,
Handler: RequestIPHandler(TimeHandler{}),
}
err := server.ListenAndServe()
if err != nil {
if err != http.ErrServerClosed {
panic(err)
}
}
}

3
ch13/2/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch13/2
go 1.25.0

86
ch13/3/ch13_3.go Normal file
View File

@@ -0,0 +1,86 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"log/slog"
"net"
"net/http"
"time"
)
type RFCTime struct {
DayOfWeek string `json:"day_of_week"`
DayOfMonth int `json:"day_of_month"`
Month string `json:"month"`
Year int `json:"year"`
Hour int `json:"hour"`
Minute int `json:"minute"`
Second int `json:"second"`
}
type TimeHandler struct{}
func StructToJsString(data any) string {
var b bytes.Buffer
enc := json.NewEncoder(&b)
err := enc.Encode(data)
if err != nil {
slog.Error("Problems with encoding json")
}
return b.String()
}
func (th TimeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
headerAccept := http.Header.Get(r.Header, "Accept")
var output string
switch headerAccept {
case "application/json":
currTime := time.Now()
rfcTime := RFCTime{
DayOfWeek: currTime.Weekday().String(),
DayOfMonth: currTime.Day(),
Month: currTime.Month().String(),
Year: currTime.Year(),
Hour: currTime.Hour(),
Minute: currTime.Minute(),
Second: currTime.Second(),
}
output = StructToJsString(rfcTime)
default:
output = time.Now().Format(time.RFC3339)
}
w.Write([]byte(output))
}
func RequestToIP(r *http.Request) string {
ip, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
slog.Error(fmt.Sprintf("Wrong format of address: %q", r.RemoteAddr))
}
return ip
}
func RequestIPHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
slog.Info(RequestToIP(r))
h.ServeHTTP(w, r)
})
}
func main() {
server := http.Server{
Addr: ":10100",
ReadTimeout: 30 * time.Second,
WriteTimeout: 90 * time.Second,
IdleTimeout: 120 * time.Second,
Handler: RequestIPHandler(TimeHandler{}),
}
err := server.ListenAndServe()
if err != nil {
if err != http.ErrServerClosed {
panic(err)
}
}
}

3
ch13/3/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch13/3
go 1.25.0

24
ch14/1/ch14_1.go Normal file
View File

@@ -0,0 +1,24 @@
package main
import (
"context"
"net/http"
"time"
)
type MsReq struct{}
func CreateTimeoutCtx(msReq time.Duration) func(http.Handler) http.Handler {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
reqCtx := r.Context()
reqCtx = context.WithValue(reqCtx, MsReq{}, msReq)
r.WithContext(reqCtx)
h.ServeHTTP(w, r)
})
}
}
func main() {
}

3
ch14/1/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch14/1
go 1.25.0

36
ch14/2/ch14_2.go Normal file
View File

@@ -0,0 +1,36 @@
package main
import (
"context"
"fmt"
"math/rand"
"time"
)
type RandSum struct{}
func main() {
sum := 0
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(2)*time.Second)
defer cancel()
start := time.Now()
i := 0
outLoop:
for {
select {
case <-ctx.Done():
ctx = context.WithValue(ctx, RandSum{}, "timeout")
break outLoop
default:
i++
randNum := rand.Int() % 100_000_000
//fmt.Printf("Randnum is %d\n", randNum)
sum = sum + randNum
if randNum == 1234 {
ctx = context.WithValue(ctx, RandSum{}, "number reached")
break outLoop
}
}
}
fmt.Printf("Sum is %d after %v; iterations - %d; cause - %s\n", sum, time.Since(start), i, ctx.Value(RandSum{}))
}

3
ch14/2/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch14/2
go 1.25.0

67
ch14/3/ch14_3.go Normal file
View File

@@ -0,0 +1,67 @@
package main
import (
"context"
"fmt"
"log/slog"
"net/http"
"time"
)
type TimeHandler struct{}
func (th TimeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(time.Now().Format(time.RFC3339)))
}
type Level string
const (
Debug Level = "debug"
Info Level = "info"
)
func ExtractLogLevel(ctx context.Context) Level {
return ctx.Value("log_level").(Level)
}
func StoreLogLevel(ctx context.Context, level Level) context.Context {
return context.WithValue(ctx, "log_level", level)
}
func GetLogLevelQuery(http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logLevel := r.URL.Query().Get("log_level")
if logLevel != "info" && logLevel != "debug" {
slog.Info("Wrong logLevel")
}
Log(StoreLogLevel(r.Context(), Level(logLevel)), Debug, "Test message")
})
}
func Log(ctx context.Context, level Level, message string) {
var inLevel Level
inLevel = ExtractLogLevel(ctx)
if level == Debug && inLevel == Debug {
fmt.Println(message)
}
if level == Info && (inLevel == Debug || inLevel == Info) {
fmt.Println(message)
}
}
func main() {
server := http.Server{
Addr: ":10100",
ReadTimeout: 30 * time.Second,
WriteTimeout: 90 * time.Second,
IdleTimeout: 120 * time.Second,
Handler: GetLogLevelQuery(TimeHandler{}),
}
err := server.ListenAndServe()
if err != nil {
if err != http.ErrServerClosed {
panic(err)
}
}
}

3
ch14/3/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module gitea.local.lab/Lbenedar/learning_go/ch14/3
go 1.25.0