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

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,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
})
}