Go 1.26颿¥å¯ŸçïŒGreen Tea GCãgo fixããŒã«ãã¹ã¿ãã¯æé©åã®åŸ¹åºè§£èª¬
Go 1.26ã®é¢æ¥å¯ŸçãšããŠãæ°ããGreen Teaã¬ããŒãžã³ã¬ã¯ã¿ãå·æ°ãããgo fixããŒã«ãã¹ã©ã€ã¹ã®ã¹ã¿ãã¯å²ãåœãŠæé©åãªã©ãäž»èŠãªå€æŽç¹ã詳ãã解説ããŸãã

Go 1.26ã¯2026幎2æã«ãªãªãŒã¹ãããGreen Teaã¬ããŒãžã³ã¬ã¯ã¿ã®ããã©ã«ãæ¡çšãå®å
šã«å·æ°ãããgo fixããŒã«ããããŠã¹ã¿ãã¯å²ãåœãŠã®å€§å¹
ãªæé©åãå°å
¥ãããŸããããããã®å€æŽã¯Goã©ã³ã¿ã€ã ã«ãããŠè¿å¹Žæã圱é¿åã®ããæ¹åã§ãããæè¡é¢æ¥ã§ã®åºé¡é »åºŠãé«ãŸã£ãŠããŸãã
Green Tea GCïŒGCãªãŒããŒããã10ã40%åæžïŒãã¢ããã€ã¶ãŒæèŒã®æ°go fixãã¹ã©ã€ã¹ãããã³ã°ã¹ãã¢ã®ã¹ã¿ãã¯å²ãåœãŠãããããã³ãŒã倿Žãªãã§æ©æµãåããããç¹ãéèŠã§ãã
Go 1.26ã®Green Teaã¬ããŒãžã³ã¬ã¯ã¿ãšã¯äœã§ããïŒ
æš¡ç¯åçïŒ Green Teaã¯ãGo 1.26ã§æ°ãã«ããã©ã«ããšãªã£ãã¬ããŒãžã³ã¬ã¯ã¿ã§ããåŸæ¥ã®äžè²äžŠè¡ã³ã¬ã¯ã¿ã®ã¹ãã£ã³æŠç¥ã眮ãæããããŒãäžã«æ£åšããåã ã®ãªããžã§ã¯ãããã€ã³ã¿è¿œè·¡ãã代ããã«ã8 KiBã®ã¡ã¢ãªããŒãžåäœã§ã¹ãã£ã³ãè¡ããŸãããã®é£ç¶ã¡ã¢ãªã¢ã¯ã»ã¹ãã¿ãŒã³ã«ãããCPUããªãã§ããã广çã«æ©èœããå®ã¢ããªã±ãŒã·ã§ã³ã§GCãªãŒããŒãããã10ã40%åæžãããŸãã
ææ°ã®CPUïŒIntel Ice LakeãŸãã¯AMD Zen 4以éïŒã§ã¯ãGCãå°ããªãªããžã§ã¯ãã®ã¹ãã£ã³ã«SIMDãã¯ãã«åœä»€ã掻çšããããã«çŽ10%ã®æ¹åãèŠèŸŒããŸãã
远å 質åïŒ Green Teaã¯GCäžã®CPUãã£ãã·ã¥åäœãã©ã®ããã«æ¹åããŸããïŒ
åŸæ¥ã®GCã¯ããŒãäžã®ãªããžã§ã¯ããã€ã³ã¿ã远跡ãããããé »ç¹ã«ãã£ãã·ã¥ãã¹ãçºçããŠããŸãããGreen Teaã¯é£ç¶ãã8 KiBãããã¯åäœã§ããŒãžããšã«ãªããžã§ã¯ããåŠçããŸããCPUããªãã§ããã£ãã·ãŒã±ã³ã·ã£ã«ã¡ã¢ãªã¢ã¯ã»ã¹ãã¿ãŒã³ãäºæž¬ã§ãããããL1/L2ãã£ãã·ã¥ãåžžã«æå¹ãªç¶æ ã«ä¿ãããŸãããã®ããŒã«ãªãã£ã®æ¹åã10ã40%ã®ãªãŒããŒãããåæžã®äž»èŠå ã§ãã
// åŸæ¥ã®ã¢ãããŒãïŒããŒãäžã®ãã€ã³ã¿ã远跡
func scanObject(obj *mspan) {
for _, ptr := range obj.pointers {
markReachable(ptr) // ãã£ãã·ã¥ãã¹ã®å¯èœæ§ãé«ã
}
}
// Green Teaã¢ãããŒãïŒé£ç¶ããŒãžãã¹ãã£ã³
func scanPage(page *pageBlock) {
// ã·ãŒã±ã³ã·ã£ã«ãª8 KiBã¹ãã£ã³ - CPUããªãã§ããã£ã«åªãã
for offset := 0; offset < pageSize; offset += objSize {
scanSlot(page.base + offset) // ãã£ãã·ã¥ãããã®å¯èœæ§ãé«ã
}
}Green Teaã¯ãã«ãæã«GOEXPERIMENT=nogreenteagcã§ç¡å¹åã§ããŸããããã®ãªããã¢ãŠãã¯Go 1.27ã§åé€ãããäºå®ã§ãã
Go 1.26ã§ã¯ã¹ã©ã€ã¹ã®ã¹ã¿ãã¯å²ãåœãŠãã©ã®ããã«æé©åãããŸãããïŒ
æš¡ç¯åçïŒ Go 1.26ã§ã¯ãappendæäœã«ããã¹ã©ã€ã¹èç©æã®ã¹ã¿ãã¯å²ãåœãŠãæ¡åŒµãããŸãããåŸæ¥ã¯æåã®appendåŒã³åºãã§é·ã1ã®ã¹ã©ã€ã¹ãããŒãã«å²ãåœãŠããã®åŸ2ã4ã8ãšåå¢ããŠããŸãããGo 1.26ã§ã¯ã«ãŒãéå§åã«ã¹ã¿ãã¯ããŒã¹ã®å°ããªãããã³ã°ã¹ãã¢ã確ä¿ãããããæåã®æ°åã®appendã¯ããŒããäžå䜿çšããŸããã
func collectTasks(items []Item) []Task {
var tasks []Task
// Go 1.26以åïŒæåã®appendã§ããŒãã«å²ãåœãŠïŒãµã€ãº1, 2, 4...ïŒ
// Go 1.26ïŒã³ã³ãã€ã©ãã¹ã¿ãã¯ããã¯ããããã¡ãæ¿å
¥
for _, item := range items {
if item.IsReady() {
tasks = append(tasks, item.ToTask())
// æåã®çŽ4åã®appendã¯ã¹ã¿ãã¯ãããã¡ã䜿çšãããŒãå²ãåœãŠãŒã
}
}
return tasks
// ã¹ã©ã€ã¹ããšã¹ã±ãŒãããå Žåãruntime.move2heap()ããªã¿ãŒã³æã«1åã ãã³ããŒ
}远å 質åïŒ ã¹ã©ã€ã¹ã颿°ã¹ã³ãŒãããšã¹ã±ãŒãããå Žåã¯ã©ããªããŸããïŒ
ã¹ã©ã€ã¹ãããŒãã«ãšã¹ã±ãŒãããªããã°ãªããªãå ŽåïŒé¢æ°ãã¹ã©ã€ã¹ãè¿ãå Žåãªã©ïŒã§ããGo 1.26ã¯èç©äžã«ã¹ã¿ãã¯ãããã¡ã䜿çšããŸããã³ã³ãã€ã©ã¯ãªã¿ãŒã³ãã€ã³ãã§runtime.move2heap()åŒã³åºããæ¿å
¥ããæçµããŒã¿ã1åã ãããŒãã«ã³ããŒããŸããåŸæ¥ã®3å以äžã®åæããŒãå²ãåœãŠïŒãµã€ãº1ã2ã4...ïŒããæåŸã®1åã®ããŒãå²ãåœãŠã«åæžãããŸããå€ãã®ã±ãŒã¹ã§æåã®äºåå²ãåœãŠæé©åãããåªããçµæãåŸãããŸãã
Go 1.26ã§go fixããŒã«ã¯ã©ã®ããã«å€æŽãããŸãããïŒ
æš¡ç¯åçïŒ go fixããŒã«ã¯Goã¢ããã€ã¶ãŒã®ãã©ãããã©ãŒã ãšããŠå®å
šã«æžãçŽãããŸãããGoã³ãŒãããŒã¹ãææ°ã®ã€ãã£ãªã ãã³ã¢ã©ã€ãã©ãªAPIã«æŽæ°ããããã®ã¯ã³ã¯ãªãã¯ãœãªã¥ãŒã·ã§ã³ãæäŸããŸããæ°ããgo fixã¯go vetãšåãè§£æãã¬ãŒã ã¯ãŒã¯äžã«æ§ç¯ãããŠããã蚺æãæäŸããã¢ãã©ã€ã¶ãŒãä¿®æ£ã®ææ¡ãšé©çšãè¡ããããã«ãªã£ãŠããŸãã
æ°ããgo fixã®äž»ãªç¹åŸŽïŒ
- ææ°ã®Goã€ãã£ãªã ãšAPIåãã®æ°åã®ãã£ã¯ãµãŒ
//go:fix inlineãã£ã¬ã¯ãã£ãã«ãããœãŒã¹ã¬ãã«ã€ã³ã©ã€ããŒ- åäœå€æŽãŒãã®ä¿èšŒïŒæ¬çªã³ãŒãã§ãå®å šã«äœ¿çšå¯èœïŒ
- æ§ããŒã«ã®å»æ¢æžã¿ãã£ã¯ãµãŒãåé€
# çŸåšã®ã¢ãžã¥ãŒã«ã«ãã¹ãŠã®ã¢ããã€ã¶ãŒãé©çš
go fix ./...
# ããŒã«ã¯ä»¥äžã®ãããªãã¿ãŒã³ãèªåæŽæ°ïŒ
# - æ§åœ¢åŒã®ãšã©ãŒã©ããã³ã°ãfmt.Errorfã®%wã«å€æ
# - éæšå¥šAPIåŒã³åºããåŸç¶ã«çœ®æ
# - ã¬ã¬ã·ãŒãã¿ãŒã³ãã¢ãã³Goã€ãã£ãªã ã«å€æè¿œå 質åïŒ //go:fix inlineã¯ã©ã®ããã«åäœããŸããïŒ
//go:fix inlineãã£ã¬ã¯ãã£ãã¯ã颿°ãŸãã¯ã¡ãœãããgo fixã«ãããœãŒã¹ã¬ãã«ã€ã³ã©ã€ãã³ã°ã®å¯Ÿè±¡ãšããŠããŒã¯ããŸããgo fixã®å®è¡æãã¢ãããŒã·ã§ã³ããã颿°ã®åŒã³åºãç®æããã®é¢æ°æ¬äœã«çœ®ãæããããŸããããã¯ã³ã³ãã€ã©ã€ã³ã©ã€ãã³ã°ãšã¯ç°ãªããçæãããæ©æ¢°èªã§ã¯ãªããœãŒã¹ã³ãŒãã倿ããŸããã©ã€ãã©ãªäœè
ã¯ããã䜿çšããŠãã©ãããŒé¢æ°ãåŒã³åºãç®æã§ã¢ãã³ãªç䟡ç©ã«ã€ã³ã©ã€ã³åããããšã§éæšå¥šåãé²ããããŸãã
Go 1.26ã®cgoããã©ãŒãã³ã¹æ¹åã«ã€ããŠèª¬æããŠãã ãã
æš¡ç¯åçïŒ Go 1.26ã§ã¯ããã¹ãŠã®cgoåŒã³åºãã®ããŒã¹ã©ã€ã³ãªãŒããŒããããçŽ30%åæžãããŸãããã©ã³ã¿ã€ã ã¯_Psyscallããã»ããµç¶æ
ïŒcgoåŒã³åºãäžã«ãŽã«ãŒãã³ãé·ç§»ããäžéç¶æ
ïŒãæé€ããããšã§ãããå®çŸããŸããããã®é·ç§»ç¶æ
ã®åé€ã«ãããcgoåŒã³åºãããšã®ç¶æ
é·ç§»ã®åæ°ãæžå°ããã¬ã€ãã³ã·ãçŽæ¥çã«äœäžããŸãã
ããŒã¿ããŒã¹ãã©ã€ããç»ååŠçãæå·åæäœãªã©ã®Cã©ã€ãã©ãªã䜿çšããã¢ããªã±ãŒã·ã§ã³ãªã©ãé »ç¹ã«cgoåŒã³åºããè¡ãããã°ã©ã ã«ãšã£ãŠéèŠãªæ¹åã§ããã³ãŒã倿Žã¯äžèŠã§ãã
Go 1.26ã®èšèªä»æ§ã®å€æŽç¹ã¯äœã§ããïŒ
æš¡ç¯åçïŒ Go 1.26ã§ã¯2ã€ã®èšèªå€æŽãå°å ¥ãããŸããã
1. æ¡åŒµãããnew()颿°ïŒ çµã¿èŸŒã¿ã®new颿°ããªãã©ã³ããšããŠåŒãåãåããããã«ãªãã倿°ã®åæå€ãæå®ã§ããããã«ãªããŸãããåŸæ¥ãnew(T)ã¯åžžã«ãŒãå€ã®*Tãè¿ããŠããŸããã
type Config struct {
Timeout *int
MaxRetry *int
}
// Go 1.26以åïŒãã«ããŒé¢æ°ãå¿
èŠ
func intPtr(v int) *int { return &v }
func makeConfig() Config {
return Config{
Timeout: intPtr(30),
MaxRetry: intPtr(3),
}
}
// Go 1.26ïŒçŽæ¥åæå
func makeConfig() Config {
return Config{
Timeout: new(30), // 30ãæã*int
MaxRetry: new(3), // 3ãæã*int
}
}2. èªå·±åç §ãžã§ããªãã¯åïŒ ãžã§ããªãã¯åãåãã©ã¡ãŒã¿å¶çŽå ã§èªèº«ãåç §ã§ããããã«ãªããFæçå€çžæ§ãªã©ã®é«åºŠãªåæœè±¡åãã¿ãŒã³ãå®çŸå¯èœã«ãªããŸããã
type Adder[A Adder[A]] interface {
Add(A) A
}
type Vector2D struct{ X, Y float64 }
func (v Vector2D) Add(other Vector2D) Vector2D {
return Vector2D{v.X + other.X, v.Y + other.Y}
}
// å¶çŽã«ããæ»ãå€ã®åãã¬ã·ãŒãã®åãšäžèŽããããšãä¿èšŒããã
func Sum[A Adder[A]](items []A) A {
var result A
for _, item := range items {
result = result.Add(item)
}
return result
}Goã®é¢æ¥å¯Ÿçã¯ã§ããŠããŸããïŒ
ã€ã³ã¿ã©ã¯ãã£ããªã·ãã¥ã¬ãŒã¿ãŒãflashcardsãæè¡ãã¹ãã§ç·Žç¿ããŸãããã
Go 1.26ã®ãŽã«ãŒãã³ãªãŒã¯æ€åºã¯ã©ã®ããã«åäœããŸããïŒ
æš¡ç¯åçïŒ Go 1.26ã§ã¯ãruntime/pprofã«å®éšçãªgoroutineleakãããã¡ã€ã«ã¿ã€ããå°å
¥ãããŸããããªãŒã¯ãããŽã«ãŒãã³ãšã¯ããã£ãã«ãsync.Mutexãsync.Condãªã©ã®äžŠè¡åŠçããªããã£ãã§ãããã¯ãããäºåºŠãšãããã¯è§£é€ãããããšããªããŽã«ãŒãã³ãæããŸããã©ã³ã¿ã€ã ã¯ã¬ããŒãžã³ã¬ã¯ã¿ã䜿çšããŠãããã®ãªãŒã¯ãæ€åºããŸãããŽã«ãŒãã³Gãããªããã£ãPã§ãããã¯ãããŠãããPãå®è¡å¯èœãªãŽã«ãŒãã³ããå°éäžèœã§ããå ŽåãGã¯åŸ©åž°ã§ããŸããã
func processWorkItems(ws []workItem) ([]workResult, error) {
ch := make(chan result)
for _, w := range ws {
go func() {
res, err := processWorkItem(w)
ch <- result{res, err} // æ©æãªã¿ãŒã³æã«ãŽã«ãŒãã³ãããã§ãããã¯
}()
}
for range len(ws) {
r := <-ch
if r.err != nil {
return nil, r.err // æ®ãã®ãŽã«ãŒãã³ããªãŒã¯
}
}
return results, nil
}
// æ€åºãæå¹åïŒGOEXPERIMENT=goroutineleakprofile
// ãšã³ããã€ã³ãïŒ/debug/pprof/goroutineleakGCã®å°éå¯èœæ§è§£æã掻çšãããããæåã®ã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ãªãã§åºç¯ãªãªãŒã¯ãæ€åºã§ããŸããGo 1.27ã§ããã©ã«ãæå¹åãããäºå®ã§ãã
Go 1.26ã§å°å ¥ãããã»ãã¥ãªãã£æ¹åã¯äœã§ããïŒ
æš¡ç¯åçïŒ æ³šç®ãã¹ã2ã€ã®ã»ãã¥ãªãã£æ¹åããããŸãã
ããŒãããŒã¹ã¢ãã¬ã¹ã®ã©ã³ãã åïŒ64ããããã©ãããã©ãŒã ïŒïŒ ã©ã³ã¿ã€ã ã¯èµ·åæã«ããŒãããŒã¹ã¢ãã¬ã¹ãã©ã³ãã åããããã«ãªããŸãããããã«ãããcgoãä»ããè匱æ§ã®æªçšæã«æ»æè
ãã¡ã¢ãªã¢ãã¬ã¹ãäºæž¬ããããšãå°é£ã«ãªããŸããGoããŒãã¡ã¢ãªã«å¯ŸããASLRçãªé²åŸ¡æ©èœã§ããGOEXPERIMENT=norandomizedheapbase64ã§ç¡å¹åã§ããŸãã
ãã¹ãéåæå·ã®ããã©ã«ãæå¹åïŒ TLSæ¥ç¶ã§ã¯ãã€ããªããéµäº€æãããã©ã«ãã§äœ¿çšãããããã«ãªããŸããïŒSecP256r1MLKEM768ãSecP384r1MLKEM1024ïŒãå€å
žçãªæ¥åæ²ç·æå·ãšML-KEMïŒæ§CRYSTALS-KyberïŒãçµã¿åãããéåèæ§ãå®çŸããŠããŸããcrypto/mlkemããã±ãŒãžã®ã«ãã»ã«å/è±ã«ãã»ã«åãçŽ18%é«éåãããŸããã
Go 1.26ã®æšæºã©ã€ãã©ãªã®ããã©ãŒãã³ã¹æ¹åã«ã€ããŠèª¬æããŠãã ãã
æš¡ç¯åçïŒ ããã€ãã®æšæºã©ã€ãã©ãªé¢æ°ãéç¹çã«æé©åãããŸããã
| 颿° | æ¹å | 詳现 |
|------|------|------|
| fmt.ErrorfïŒãã©ãŒãããåè©ãªãïŒ | çŽ92%é«éå | ãã©ãŒããããªãåŒã³åºããerrors.Newãšåçã®æ§èœã« |
| io.ReadAll | çŽ2åé«éãã¡ã¢ãª50%åæž | ç·åœ¢æé·ããææ°é¢æ°çãããã¡æé·ã«å€æŽ |
| crypto/mlkem | çŽ18%é«éå | ã«ãã»ã«åã»è±ã«ãã»ã«åã®æé©å |
| image/jpeg | é«éåã»é«ç²ŸåºŠå | æ°ãããšã³ã³ãŒã/ãã³ãŒãå®è£
|
ããã«ãbytes.Bufferã«Peek()ã¡ãœãããerrorsã«ãžã§ããªãã¯AsType()颿°ãreflectã«ã€ãã¬ãŒã¿ã¡ãœããïŒType.Fields()ãType.Methods()ãValue.Fields()ïŒã远å ãããGoã®range-over-funcãã¿ãŒã³ãšæŽåããŠããŸãã
æ°ããerrors.AsType颿°ã¯ãšã©ãŒãã³ããªã³ã°ãã©ã®ããã«ç°¡çŽ åããŸããïŒ
æš¡ç¯åçïŒ errors.AsType[T]()ã¯errors.As()ã®ãžã§ããªãã¯ä»£æ¿ã§ããAsãåŒã³åºãåã«ã¿ãŒã²ãã倿°ã宣èšããå¿
èŠããªããªãããã€ã©ãŒãã¬ãŒãã³ãŒããåæžãããŸãã
// Go 1.26以åïŒ2段éã®ããã»ã¹
var pathErr *os.PathError
if errors.As(err, &pathErr) {
log.Printf("path error on %s: %v", pathErr.Path, pathErr.Err)
}
// Go 1.26ïŒåäžã®åŒ
if pathErr, ok := errors.AsType[*os.PathError](err); ok {
log.Printf("path error on %s: %v", pathErr.Path, pathErr.Err)
}ãžã§ããªãã¯çã¯ã³ã³ãã€ã«æã«åå®å šã§ãããæ¡ä»¶ãã§ãŒã³ã§ããèªç¶ã«èªããŸãã
Goã®é¢æ¥å¯Ÿçã¯ã§ããŠããŸããïŒ
ã€ã³ã¿ã©ã¯ãã£ããªã·ãã¥ã¬ãŒã¿ãŒãflashcardsãæè¡ãã¹ãã§ç·Žç¿ããŸãããã
ãŸãšã
- Green Tea GCã¯ãã€ã³ã¿è¿œè·¡ã®ä»£ããã«8 KiBã¡ã¢ãªããŒãžãã¹ãã£ã³ããã³ãŒã倿Žãªãã§GCãªãŒããŒãããã10ã40%åæžãã
- ã¹ã©ã€ã¹ãããã³ã°ã¹ãã¢ã®ã¹ã¿ãã¯å²ãåœãŠã«ãããappendã«ãŒãäžã®3å以äžã®åæããŒãå²ãåœãŠãæé€ããããšã¹ã±ãŒãæã«ã®ã¿1åã®ããŒãã³ããŒãè¡ããã
- å·æ°ããã
go fixããŒã«ã¯go vetè§£æãã¬ãŒã ã¯ãŒã¯äžã«æ§ç¯ãããæ°åã®ã¢ããã€ã¶ãŒãé©çšããåäœå€æŽãŒããä¿èšŒããã new()ãåŒãåãåããããã«ãªãããã€ã³ã¿ãã«ããŒé¢æ°ãäžèŠã«ãªã£ã- èªå·±åç §ãžã§ããªãã¯åå¶çŽã«ããFæçå€çžæ§ãã¿ãŒã³ãå®çŸå¯èœã«ãªã£ã
- ãŽã«ãŒãã³ãªãŒã¯æ€åºïŒå®éšçïŒãGCå°éå¯èœæ§ãå©çšããŠæ°žç¶çã«ãããã¯ããããŽã«ãŒãã³ãæ€åºãã
fmt.ErrorfïŒãã©ãŒãããåè©ãªãïŒã92%é«éåãio.ReadAllã®ã¡ã¢ãªäœ¿çšéã50%åæžããã- ãã¹ãéåãã€ããªããéµäº€æãTLSæ¥ç¶ã§ããã©ã«ãæå¹ã«ãªã£ã
Go颿¥ã®è³ªåã«åããŠããããã®ã©ã³ã¿ã€ã 倿Žãçè§£ããããšãéèŠã§ããGo䞊è¡åŠçã¬ã€ãã§ã¯ãããã§åãäžãããªãŒã¯æ€åºæ©èœãè£å®ããåºæ¬çãªãŽã«ãŒãã³ãã¿ãŒã³ã解説ããŠããŸãã
ä»ããç·Žç¿ãå§ããŸãããïŒ
颿¥ã·ãã¥ã¬ãŒã¿ãŒãšæè¡ãã¹ãã§ç¥èããã¹ãããŸãããã
ã¿ã°
å ±æ
é¢é£èšäº

Go ãšã©ãŒãã³ããªã³ã° 2026幎çïŒãã¿ãŒã³ãã©ããã³ã°ãæè¡é¢æ¥ã®é »åºè³ªå
Goã®ãšã©ãŒãã³ããªã³ã°ãã¿ãŒã³ãç¶²çŸ çã«è§£èª¬ãã»ã³ããã«ãšã©ãŒãã«ã¹ã¿ã åãerrors.Isã»errors.Asã%wã«ãããšã©ãŒã©ããã³ã°ãæè¡é¢æ¥ã§é »åºã®è³ªåãŸã§å¹ åºãã«ããŒã

Goãã¶ã€ã³ãã¿ãŒã³ïŒGoéçºè ãæŒãããã¹ãå¿ é ãã¿ãŒã³ãšé¢æ¥å¯Ÿç
Goã®èšèšææ³ã«åºã¥ããã¶ã€ã³ãã¿ãŒã³ãäœç³»çã«è§£èª¬ãFunctional OptionsãStrategyãObserverãMiddlewareãªã©ã颿¥ã§åãããå®è·µçãã¿ãŒã³ãšãã®åçäŸã玹ä»ããŸãã

Go颿¥ã®é »åº25å: éçºè åãå®å šã¬ã€ã
é »åº25åã§Goã®é¢æ¥ãå¶ããããŽã«ãŒãã³ããã£ãã«ãã€ã³ã¿ãŒãã§ãŒã¹ã䞊è¡åŠçãã¿ãŒã³ãã³ãŒãäŸãšãšãã«è§£èª¬ã