Go1.25が8月13日にリリースされ、リリースノートやブログが公開されています。この記事では前回のGo1.24 New Features に引き続き、Go1.25の新機能の中から気になった機能を紹介していきます。
spec
Go1.25では既存のGoのコードに影響を与える言語仕様の変更はありません。ただし、core typeの概念が削除され、専用の文章に置き換えられました。
詳細については、公式ブログをご参照ください。
go command
go build -asan
オプションは、プログラム終了時にデフォルトでメモリリークを検出するようになりました。
これは、Cによって割り当てられたメモリが解放されず、CまたはGoによって割り当てられた他のメモリから参照されていない場合にエラーを出します。
このエラーは、ASAN_OPTIONS=detect_leaks=0
を設定することで無効にできます。
事前にビルドされたツールが一部リリースに含まれなくなります。コンパイラやリンカなどのコアツールチェーンのバイナリは引き続き含まれますが、ビルドやテスト、フォーマットで頻繁に呼び出されないツールは含まれません。
削除対象となるツールはaddr2line
、buildid
、nm
、objdump
、pprof
、test2json
、trace
などです。これらのツールのソースコードは引き続きGOROOTに含まれるため、初回実行時に自動的にビルドされ、キャッシュされます。既存のワークフローに影響を与えることなく、配布パッケージのサイズを大幅に縮小することが可能になります。
参考としてgo1.x.linux-amd64.tar.gzのサイズは1.24.0が75MBなのに対し、1.25.0が57MBと削減されています。
新しいgo.mod
のignore
ディレクティブを使用して、go
コマンドが無視するディレクトリを指定できます。指定したディレクトリとそのサブディレクトリ内のファイルは、all
や./...
などのパターンにマッチするとき無視されますが、モジュールのzipファイルには引き続き含まれます。
この機能は、多言語プロジェクトにおいて特に有用です。例えば、node_modules
やBazelが生成するbazel-*
ディレクトリなど、大量のファイルを含むディレクトリがある場合、go build ./...
やgo test ./...
の実行時間を大幅に短縮できます。また、gopls
のCPU使用率も改善されます。
使用例
// go.mod
module example.com/myproject
go 1.25
ignore node_modules
ignore bazel-*
ignore .build
新しいgo doc -http
オプションは、要求されたオブジェクトのドキュメントを表示するドキュメントサーバーを起動し、ブラウザでドキュメントを表示します。
新しいgo version -m -json
オプションは、指定されたGoのバイナリファイルに埋め込まれたビルド情報(runtime/debug.BuildInfo
)をJSON形式で出力します。
type BuildInfo struct {
GoVersion string
Path string
Main Module
Deps []*Module
Settings []BuildSetting
}
go
コマンドは、構文を使用してモジュールパスを解決する際に、リポジトリのサブディレクトリをモジュールルートのパスとして使用できるようになりました。これにより、
root-path
がバージョン管理システムvcs
を持つrepo-url
のsubdir
に対応することを示します。
特に単一のリポジトリ内で複数のGoモジュールを管理し、それぞれに異なるカスタムインポートパスを割り当てることが可能になるため、マイクロサービスアーキテクチャやモノレポ構成において有用です。
meta go-import
の設定方法
meta go-import
タグは、カスタムインポートパスを設定するためのHTMLのmetaタグで、Webサーバーのレスポンスのセクションに記載します。
DOCTYPE html>
html>
head>
meta name="go-import" content="example.com/mymodule git https://github.com/user/mymodule">
head>
body>
p>Go to a href="https://github.com/user/mymodule">GitHub repositorya>p>
body>
html>
動作
- ユーザーが
go get example.com/mymodule
を実行 - Goコマンドが
https://example.com/mymodule?go-get=1
にHTTPリクエストを送信 - サーバーがmetaタグを含むHTMLを返却
- Goコマンドがmetaタグの情報を使って実際のリポジトリからコードを取得
新しいwork
パッケージパターンは、work(以前はmainと呼ばれていた)モジュール内のすべてのパッケージにマッチします。
使用例
go build work
go test work
go vet work
モジュールモードとワークスペースモードでの挙動の違い
goコマンドがgo.mod
またはgo.work
ファイルのgo
ディレクティブを更新する際、コマンドの現在のバージョンを指定するtoolchainディレクティブを追加しなくなりました。
vet
go vet
コマンドに新しいアナライザが含まれます。
waitgroup: sync.WaitGroup.Add
を不適切に使用している場合に検出されます。
問題のあるコード
var wg sync.WaitGroup
for i := 0; i 5; i++ {
go func() {
wg.Add(1)
defer wg.Done()
}()
}
wg.Wait()
正しいコード
var wg sync.WaitGroup
for i := 0; i 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
}()
}
wg.Wait()
hostport: fmt.Sprintf("%s:%d", host, port)
の形式でnet.Dial
用アドレスを構築している場合に、net.JoinHostPort
を代わりに提案します。これは前者がIPv6アドレスを扱う際に、省略記法により意図しない表記をしてしまう可能性があるためです。
addr := fmt.Sprintf("%s:%d", host, port)
addr := net.JoinHostPort(host, strconv.Itoa(port))
runtime
GOMAXPROCS
のデフォルト動作が変更されました。Goの以前のバージョンでは、GOMAXPROCS
は起動時に利用可能な論理CPU数(runtime.NumCPU
)がデフォルトで設定されていました。Go1.25では2つの変更点が追加されています。
-
Linuxでは、ランタイムはプロセスを含むcgroupのCPU帯域幅制限を考慮します。CPU帯域幅制限によるCPU数が論理CPU数より低い場合、
GOMAXPROCS
はより低い値に設定されます。Kubernetesなどのコンテナランタイムシステムでは、cgroupのCPU帯域幅制限は一般的に「CPU limit」オプションに対応します。「CPU requests」オプションは考慮しません。 -
すべてのOSで、論理CPU数やcgroupのCPU帯域幅制限が変更された場合、ランタイムは定期的に
GOMAXPROCS
を更新します。
これらの動作は両方とも、GOMAXPROCS
環境変数またはruntime.GOMAXPROCS
によって手動でGOMAXPROCS
が設定されている場合、自動的に無効になります。GODEBUGの設定 containermaxprocs=0
とupdatemaxprocs=0
でそれぞれ明示的に無効にすることもできます。
更新されたcgroup制限の読み取りをサポートするため、ランタイムはプロセスの存続期間中、cgroupファイル用にキャッシュされたファイルディスクリプタを保持します。
詳しくは公式ブログをご参照ください。
既存のガベージコレクタの一部を置き換える新しいガベージコレクタが実験的に利用できるようになりました。このガベージコレクタの設計は、より良い局所性とCPUスケーラビリティを通じて小さなオブジェクトのマーキングとスキャンの性能を向上させます。ベンチマーク結果は様々ですが、ガベージコレクションを頻繁に実行する実際的なプログラムでは、ガベージコレクションのオーバーヘッドが10〜40%程度削減される見込みです。
新しいガベージコレクタは、ビルド時にGOEXPERIMENT=greenteagc
を設定して有効化できます。
ちなみに新しいガベージコレクタはGreen Teaと呼ばれていて、命名の由来はメインで実装したAustin Clements氏が、日本滞在中に毎日抹茶を飲みながらアルゴリズム開発の進捗を多く生めたからだそうです。
上記のGo Timeやプロポーザルでも言及されていますが、SIMDの活用などまだまだ改善する余地があるとのことで、今後さらにパフォーマンスの改善が期待できそうです。
ランタイムの実行トレースは長い間、アプリケーションの低レベル動作を理解し、デバッグするための強力で負荷の高い手段を提供してきました。しかしながら、実行トレースを継続的にファイルに書き込むコストとそのサイズのため、一般的に稀にしか発生しないイベントのデバッグでは実用的ではありませんでした。
新しいruntime/trace.FlightRecorder
は、トレースをメモリ内のリングバッファに継続的に記録することで、ランタイムの実行トレースをキャプチャする軽量な手段を提供します。重要なイベントが発生した際、プログラムはFlightRecorder.WriteTo
を呼び出し、過去数秒間のトレースをファイルに書き込むことができます。
FlightRecorder
によってキャプチャされる時間の長さとデータ量は、FlightRecorderConfig
内で設定できます。
使用例
recorder := trace.NewFlightRecorder(
trace.FlightRecorderConfig{
MinAge: 5 * time.Second,
MaxBytes: 0,
},
)
recorder.Start()
defer recorder.Stop()
file, _ := os.Create("trace.out")
recorder.WriteTo(file)
panicをrecover後に再びpanicが発生し、recoverしないままプログラムが終了する場合に出力されるメッセージは、出力する値が同じであれば繰り返し表示されなくなりました。
Go1.25以前は以下のように出力していました。
panic: PANIC [recovered]
panic: PANIC
Go1.25からは以下のようにされます。
panic: PANIC [recovered, repanicked]
出力する値が異なれば従来通りのメッセージが出力されます。
panic: PANIC1 [recovered]
panic: PANIC2
匿名仮想メモリ領域(VMA: Virtual Memory Area)名のカーネルサポート(CONFIG_ANON_VMA_NAME
)があるLinuxでは、Goランタイムは匿名メモリマッピングにその目的に関する情報を付加するようになります。例えば、ヒープメモリに対して[anon: Go: heap]
のような具合です。これはGODEBUGの設定 decoratemappings=0
で無効にできます。
匿名VMAとは
- 匿名メモリ: 特定のファイルに結び付いていないメモリ領域(プログラムが動的に割り当てるメモリ)
- VMA: Linuxカーネルがメモリ領域を管理する単位
before/after
-
before:
/proc/[pid]/maps
で表示される際、用途が不明で「[anon]」とのみ表示 -
after: 「
[anon: Go: heap]
」「[anon: Go: stack]
」などのコンテキストに即した情報を付与
compiler
Go1.25で、Go 1.21で混入したバグが修正されました。このバグはnilポインタチェックを不正に遅延させる可能性がありました。以下のように(不正に)正常に実行されていたプログラムは、今後(正しく)nilポインタ例外でパニックします。
package main
import "os"
func main() {
f, err := os.Open("nonExistentFile")
name := f.Name()
if err != nil {
return
}
println(name)
}
このプログラムは、エラーをチェックする前にos.Open
の結果を使用しているため正しくありません。err
がnon-nilの場合f
の結果はnilであり、その場合f.Name()
は内部でf.name
とnilのフィールドを参照しているのでパニックすべきです。しかし、Go 1.21から1.24では、コンパイラはnilチェックをエラーチェック後まで不正に遅延させ、プログラムが正常に実行されていました。これはGoの仕様に違反しています。Go1.25では正常に実行されません。(ちなみにf.Name()
が呼ばれた時点でpanicはしないのは仕様通りです)
※リリースノートのサンプルコードだと分かりずらいので補足
以下のコードをGo1.25以前で実行した場合、panicにならずに③を出力してプログラムが正常終了します。そしてGo1.25以前のバージョンのまま②or④のコメントアウトを外して実行すると、①でpanicとなります。Go1.25以降で実行した場合は②or④のコメントアウトを外さずとも①でpanicするようになります。
package main
import (
"fmt"
)
func main() {
m := map[string]*struct {
field int
}{}
t, ok := m[""]
valid := t.field > 0
if !ok || !valid {
fmt.Printf("got: %v\n", t)
}
}
Go1.25のコンパイラとリンカは、DWARFバージョン5を使用してデバッグ情報を生成するようになりました。新しいDWARFバージョンは、Goバイナリのデバッグ情報に必要なメモリを削減し、特に大きなGoバイナリに対してリンク時間を短縮します。
デバッガへの影響
- 起動の高速化: デバッグ情報のサイズ削減により、起動時間が短縮される可能性
- メモリ使用量の削減: デバッガがロードするデバッグ情報が少なくなるため、メモリ効率が向上
コンパイラは、より多くの状況でスライスのバッキングストア(スライスを構成するarray, len, capといった情報)をスタックに割り当てることができるようになり、性能が向上しました。この変更は、不適切にunsafe.Pointerを使用した場合、影響する可能性があります。例としてissue73199を参照してください。これらの問題を追跡するために、bisectツールを-compile=variablemake
フラグと組み合わせて使用して、問題の原因となる割り当てを見つけることができます。このような新しいスタック割り当ては-gcflags=all=-d=variablemakehash=n
を使用してオフにすることもできます。
linker
リンカは-funcalign=N
コマンドラインオプションを受け入れるようになりました。これは関数エントリのアライメントを指定します。
デフォルト値はプラットフォーム依存であり、このリリースでは変更されていません。
new packages
testing/synctest
testing/synctest
パッケージは、並行処理を行うコードのテストをサポートします。
Test
関数は、隔離されたスコープである「バブル」内でテスト関数を実行します。バブル内では、時間は仮想化されます。time
パッケージの処理は疑似クロックで動作し、バブル内のすべてのgoroutineがブロックされている場合、クロックは瞬時に進みます。
Wait
関数は、現在のバブル内のすべてのgoroutineがブロックされるまで待ちます。
encoding/json/v2
Go1.25では、ビルド時に環境変数GOEXPERIMENT=jsonv2
を有効にすることで、JSONの新しい実装を使用できます。
有効にした場合、2つの新しいパッケージが利用可能になります。
-
encoding/json/v2
パッケージは、encoding/json
パッケージの代替です- より良い性能: Marshal/Unmarshal処理の大幅な高速化
- メモリ効率: ガベージコレクションの負荷を軽減する設計
- ストリーミングサポート: 大きなJSONデータのストリーム処理
- 型安全性の向上: より厳密な型チェックとエラーハンドリング
- カスタマイゼーション: フィールドの命名規則やフォーマットの細かい制御
- 互換性の改善: 様々なJSONバリアントとの相互運用性
- エラー情報の詳細化: デバッグしやすいエラーメッセージ
-
encoding/json/jsontext
パッケージは、JSON構文の低レベル処理を提供します- ストリーミングJSON読み取り・書き込みAPIを提供
- トークンレベルでのJSON解析と生成が可能
- メモリ効率的なJSON処理を実現
- カスタムJSONフォーマットの実装をサポート
- 既存の
encoding/json
パッケージの基盤として機能
さらに、jsonv2が有効な場合、
-
encoding/json
パッケージは内部でencoding/json/v2を使用します。MarshallingとUnmarshallingの動作は影響を受けませんが、パッケージ関数によって返されるエラーのテキストが変更される可能性があります -
encoding/json/v2
パッケージには、MarshallerとUnmarshallerを実装する際に使用できる多くのオプションやstruct tagが追加されます
v2では多くのシナリオでv1よりも大幅に優れた性能を発揮します。基本的に、Marshalの性能は同等であり、Unmarshalはv2で大幅な高速化を見込めます。より詳細な分析については、github.com/go-json-experiment/jsonbenchリポジトリを参照してください。
詳細についてはプロポーザルやパッケージのコメントをご参照ください。
v1からv2へのマイグレーションについてはMigrating to v2を参照してください。
minor changes to packages
archive/tar
Writer.AddFS
メソッドは、io/fs.ReadLinkFS
を実装するfs.FS
でシンボリックリンクをサポートするようになりました。
encoding/asn1
Unmarshal
とUnmarshalWithParams
は、ASN.1タイプのT61StringとBMPStringをより一貫して解析するようになりました。これにより、以前受け入れられていた一部の不正な形式のエンコードが拒否される可能性があります。
crypto
MessageSigner
は、署名するメッセージを自分でハッシュ化できる新しい署名インターフェースです。新しい関数SignMessage
も導入され、Signer
インターフェースをMessageSigner
にアップグレードしようと試み、成功した場合はMessageSigner.SignMessage
メソッドを使用し、そうでなければSigner.Sign
を使用します。これは、Signer
とMessageSigner
の両方をサポートしたいコードで使用できます。
プログラム開始後にGODEBUG設定のfips140
を変更しても何も起きなくなりました。以前は許可されていないと文書化されており、変更された場合にパニックを引き起こす可能性がありました。
SHA-1、SHA-256、SHA-512は、AVX2命令が利用できない場合、amd64でより遅くなりました。2015年以降に製造されたほとんどすべてのプロセッサはAVX2をサポートしています。
crypto/ecdsa
新しいParseRawPrivateKey
、ParseUncompressedPublicKey
、PrivateKey.Bytes
、PublicKey.Bytes
関数とメソッドは、低レベルのエンコーディングを実装し、crypto/elliptic
やmath/big
関数とメソッドを駆使しなくてよくなりました。
従来の実装との比較
従来、ECDSAキーの生のバイト形式との変換には、楕円曲線の数学的操作や大きな整数の処理が必要でした。
func privateKeyToBytes(priv *ecdsa.PrivateKey) []byte {
return priv.D.Bytes()
}
func publicKeyToBytes(pub *ecdsa.PublicKey) []byte {
x := pub.X.Bytes()
y := pub.Y.Bytes()
uncompressed := make([]byte, 1+len(x)+len(y))
uncompressed[0] = 0x04
copy(uncompressed[1:], x)
copy(uncompressed[1+len(x):], y)
return uncompressed
}
func privateKeyToBytes(priv *ecdsa.PrivateKey) []byte {
return priv.Bytes()
}
func publicKeyToBytes(pub *ecdsa.PublicKey) []byte {
return pub.Bytes()
}
func bytesToKeys(privBytes, pubBytes []byte) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) {
priv, err := ecdsa.ParseRawPrivateKey(privBytes)
if err != nil {
return nil, nil, err
}
pub, err := ecdsa.ParseUncompressedPublicKey(pubBytes)
if err != nil {
return nil, nil, err
}
return priv, pub, nil
}
この変更により、開発者は楕円曲線暗号の数学的詳細を理解することなく、ECDSAキーの生のバイト表現を安全かつ効率的に処理できるようになります。
FIPS 140-3モードが有効な場合、署名は4倍高速になり、非FIPSモードの性能と一致します。
crypto/ed25519
FIPS 140-3モードが有効な場合、署名は4倍高速になり、非FIPSモードの性能と一致します。
crypto/elliptic
Curve
インターフェースの実装の一部で文書化されていないInverse
とCombinedMult
メソッドが実装されていましたが削除されました。
crypto/rsa
PublicKey
は、modulus値が秘匿されているとは言えなくなりました。VerifyPKCS1v15
とVerifyPSS
は、すべての入力が公開されリークする可能性があることをすでに警告しており、他の公開値からmodulusを復元できる数学的攻撃が存在します。
鍵生成は3倍高速になりました。
crypto/sha1
SHA-NI命令が利用可能な場合、amd64でハッシュ化が2倍高速になりました。
crypto/sha3
新しいSHA3.Clone
メソッドはhash.Cloner
を実装します。
Apple M系プロセッサでハッシュ化が2倍高速になりました。
crypto/tls
新しいConnectionState.CurveID
フィールドは、接続を確立するために使用された鍵交換メカニズムを公開します。
新しいConfig.GetEncryptedClientHelloKeys
コールバックは、クライアントがEncrypted Client Hello拡張を送信する際にサーバーが使用するEncryptedClientHelloKey
を設定するために使用できます。
RFC 9155に従い、SHA-1署名アルゴリズムはTLS 1.2ハンドシェイクで許可されなくなりました。
これらはGODEBUGの設定のtlssha1=1
で再び有効化できます。
FIPS 140-3モードが有効な場合、TLS 1.2でExtended Master Secretが必要になり、Ed25519とX25519MLKEM768が許可されるようになりました。
TLSサーバーは、クライアントの最も優先されるプロトコルバージョンでなくても、最高のサポートされるプロトコルバージョンを優先するようになりました。
TLSクライアントとサーバーの両方が、仕様に従うことと仕様外の動作を拒否することにおいて、より厳格になりました。準拠するピアとの接続は影響を受けないはずです。
crypto/x509
CreateCertificate
、CreateCertificateRequest
、CreateRevocationList
は、crypto.Signer
だけでなくcrypto.MessageSigner
署名インターフェースも受け入れることができるようになりました。これにより、これらの関数は、呼び出し元によってではなく署名操作の一部としてハッシュが行われる「ワンショット」署名インターフェースを実装する型を使用することができます。
CreateCertificate
は、SubjectKeyId
が不足している場合、切り詰められたSHA-256を使用してそれを設定するようになりました。
GODEBUGの設定のx509sha256skid=0
でSHA-1に戻します。
ParseCertificate
は、負のpathLenConstraintを含むBasicConstraints拡張を含む証明書を拒否するようになりました。
ParseCertificate
は、ASN.1 T61StringとBMPString型でエンコードされた文字列をより一貫して処理するようになりました。これにより、以前受け入れられていた一部の不正な形式のエンコーディングが拒否される可能性があります。
debug/elf
debug/elf
パッケージはRISC-V ELF解析用の2つの新しい定数を追加します。
go/ast
FilterPackage
、PackageExports
、MergePackageFiles
関数、およびMergeMode
型とその定数は、長期間非推奨のObject
とPackage
機構でのみ使用されているため、すべて非推奨となります。
新しいPreorderStack
関数は、Inspect
と同様に構文木を巡回し、サブツリーへの降下を制御しますが、便宜上、ノードの各ポイント以下のスタックも提供します。
go/parser
ParseDir
関数は非推奨になります。
go/token
新しいFileSet.AddExistingFiles
メソッドは、既存のFile
をFileSet
に追加することを可能にし、または任意のFile
セットに対してFileSet
を構築することを可能にし、長時間実行されるアプリケーションで単一のグローバルFileSet
に関連する問題を軽減します。
go/types
Var
は、変数を以下のいずれかとして分類するVar.Kind
メソッドを持つようになりました:パッケージレベル変数、レシーバ変数、引数、戻り値、ローカル変数、または構造体フィールド。
新しいLookupSelection
関数は、既存のLookupFieldOrMethod
関数と同様に、指定された名前とレシーバ型のフィールドまたはメソッドを検索しますが、結果をSelection
の形式で返します。
hash
新しいXOF
インターフェースは、SHAKEなどの任意または無制限の出力長を持つハッシュ関数である「拡張可能出力関数」によって実装できます。
新しいCloner
インターフェースを実装するハッシュは、その状態のコピーを返すことができます。すべてのHash
の実装は現在Cloner
を実装しています。
hash/maphash
新しいHash.Clone
メソッドはhash.Cloner
を実装します。
io/fs
新しいReadLinkFS
インターフェースは、ファイルシステム内のシンボリックリンクを読み取る能力を提供します。
log/slog
GroupAttrs
はAttr
値のスライスからグループAttr
を作成します。
Record
は、ソース位置を返すか、利用できない場合はnilを返すSource
メソッドを持つようになりました。
mime/multipart
新しいヘルパー関数FileContentDisposition
は、マルチパートContent-Dispositionヘッダーフィールドを構築します。
net
LookupMX
とResolver.LookupMX
は、有効なIPアドレスのように見えるDNS名と有効なドメイン名を返すようになりました。
具体的な変更内容
Go1.24以前では、MXレコードの値として192.168.1.100
のようなIPアドレスが返された場合、RFC 5321の厳密な要求に従ってこれらの値は破棄されていました。しかし、実際の運用環境では、一部のネームサーバーや設定でMXレコードにIPアドレスが設定されることがあります。
返される値の例
mx, err := net.LookupMX("example.com")
if err != nil {
log.Fatal(err)
}
for _, record := range mx {
fmt.Printf("Priority: %d, Host: %s\n", record.Pref, record.Host)
}
この変更により、RFC要求よりも実用性を重視し、実際のインフラで動作しているメールシステムとの互換性が向上します。
WindowsでLookupMXは、ListenMulticastUDP
がIPv6アドレスをサポートするようになりました。
Windowsでは、os.File
とネットワーク接続間の変換が可能になりました。具体的には、FileConn
、FilePacketConn
、FileListener
関数が実装され、開いているファイルに対応するネットワーク接続またはリスナーを返します。
同様に、TCPConn
、UDPConn
、UnixConn
、IPConn
、TCPListener
、UnixListener
のFile
メソッドが実装され、ネットワーク接続の基礎となるos.File
を返します。
net/http
新しいCrossOriginProtection
は、安全でないクロスオリジンブラウザのリクエストを拒否することにより、Cross-Site Request Forgery(CSRF)に対する保護を実装します。
これはモダンブラウザのFetchメタデータを使用し、トークンやクッキーを必要とせず、オリジンベースとパターンベースのバイパスをサポートします。
使用例
package main
import (
"fmt"
"net/http"
)
func main() {
protection := http.CrossOriginProtection{}
http.Handle("/api/", protection.Wrap(http.HandlerFunc(apiHandler)))
protectionWithAllowlist := http.CrossOriginProtection{
AllowedOrigins: []string{
"https://trusted-app.example.com",
"https://*.internal.company.com",
},
}
http.Handle("/admin/", protectionWithAllowlist.Wrap(http.HandlerFunc(adminHandler)))
devProtection := http.CrossOriginProtection{
AllowedOrigins: []string{
"http://localhost:*",
},
}
http.Handle("/dev-api/", devProtection.Wrap(http.HandlerFunc(devHandler)))
http.ListenAndServe(":8080", nil)
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Secure API endpoint accessed safely")
}
func adminHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Admin function executed")
}
func devHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Development API")
}
動作の仕組み
-
自動判定: ブラウザが送信する
Sec-Fetch-Site
ヘッダーを確認-
same-origin
: 同一オリジンからのリクエスト → 許可 -
cross-site
: クロスサイトリクエスト → 検証または拒否 -
none
: 直接アクセス(ブックマークなど) → 許可
-
- 設定不要: 従来のCSRFトークンやクッキーの設定が不要
- 柔軟な制御: 必要に応じて特定のオリジンを許可リストに追加可能
この機能により、モダンなブラウザでのCSRF攻撃を簡単かつ効果的に防ぐことができます。
os
Windowsでは、NewFile
が非同期I/O用に開かれたハンドルをサポートするようになりました(つまり、syscall.CreateFile
呼び出しでsyscall.FILE_FLAG_OVERLAPPED
が指定されている)。
これらのハンドルはGoランタイムのI/O完了ポートに関連付けられ、結果として得られるFile
に以下の利点を提供します。
この機能強化は、Windowsで名前付きパイプを介して通信するアプリケーションに特に有益です。
ハンドルは一度に1つの完了ポートにのみ関連付けることができることに注意してください。NewFile
に提供されたハンドルがすでに完了ポートに関連付けられている場合、返されるFile
は同期I/Oモードにダウングレードされます。
この場合、I/OメソッドはOSスレッドをブロックし、デッドラインメソッドは効果がありません。
DirFS
とRoot.FS
によって返されるfs.FS
は、新しいio/fs.ReadLinkFS
インターフェースを実装します。CopyFS
は、io/fs.ReadLinkFS
を実装するfs.FS
をコピーする際にシンボリックリンクをサポートします。
Root
型は以下の追加メソッドをサポートします。
reflect
新しいTypeAssert
関数は、Value
を指定された型のGoの値に直接変換することを許容します。これはValue.Interface
の結果に型アサーションを使用するのと似ていますが、不要なメモリ割り当てを避けます。
regexp/syntax
\p{name}
と\P{name}
文字クラス構文(Unicode文字クラスエスケープ)は、Any、ASCII、Assigned、Cn、LC、および\p{Letter}
(\pL
用)などのUnicodeカテゴリエイリアスの名前を受け入れるようになりました。
Unicode TR18に従い、スペース、アンダースコア、ハイフンを無視して、大文字小文字を区別しない名前検索も使用するようになりました。
runtime
AddCleanup
によってスケジュールされたクリーンアップ関数は、並行・並列に実行されるようになり、unique
パッケージのように過度にしようする場合でも効率的に実行可能になりました。個々のクリーンアップ処理が長時間実行またはブロックされて、クリーンアップキューのブロックが発生するのを避けるために、その処理は新しいgoroutineに移されるようになるはずです。
新しいGODEBUG=checkfinalizers=1
設定は、GCガイドで説明されているようなファイナライザーとクリーンアップの一般的な問題を検出するのに役立ちます。
このモードでは、ランタイムは各ガベージコレクションサイクルで診断を行い、長時間実行される問題のあるファイナライザーやクリーンアップを特定するのに役立つよう、ファイナライザーとクリーンアップキューの長さをstderrに定期的に出力します。
詳細については、GODEBUGドキュメントを参照してください。
新しいSetDefaultGOMAXPROCS
関数は、GOMAXPROCS
が設定されていない場合のデフォルト値を設定します。
runtime/pprof
ランタイム内部のロックの競合に関するmutexプロファイルは、遅延を引き起こしたクリティカルセクションの終了を正しく指すようになりました。これはsync.Mutex
の競合に対するプロファイルの動作と一致します。
sync
新しいWaitGroup.Go
メソッドは、複数のgoroutineを作成してそれらの終了を待つ一般的なパターンをより便利にします。
Go1.24以前の従来の方法
func processItems(items []string) {
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
go func(item string) {
defer wg.Done()
process(item)
}(item)
}
wg.Wait()
}
Go1.25の新しい方法
func processItems(items []string) {
var wg sync.WaitGroup
for _, item := range items {
wg.Go(func() {
process(item)
})
}
wg.Wait()
}
testing
新しいメソッドT.Attr
、B.Attr
、F.Attr
は、テストログに属性を出力します。属性は、テストに関連付けられた任意のkey-valueです。
例えば、TestF
という名前のテストで、t.Attr("key", "value")
の出力は以下のようになります。
-json
フラグを使用すると、属性は新しい「attr」アクションとして出力されます。
T
、B
、F
の新しいOutput
メソッドは、TB.Log
と同様にテストの出力に書き込めるio.Writer
を提供します。TB.Log
と同様に、出力はインデントされますが、ファイル名と行番号は含まれません。
AllocsPerRun
関数は、並列テストが実行されている場合にパニックするようになりました。AllocsPerRun
の結果は、他のテストが実行されている場合、本質的に不安定です。
新しいパニック動作は、このようなバグを検知するのに役立ちます。
testing/fstest
MapFS
はio/fs.ReadLinkFS
インターフェースを実装します。TestFS
は、io/fs.ReadLinkFS
インターフェースを実装している場合、Lstatの値を見るようになります。TestFS
は、無限に再帰することを避けるためにシンボリックリンクを追跡しなくなりました。
unicode
新しいCategoryAliases
マップは、「L」に対する「Letter」などのカテゴリエイリアス名への変換手段を提供します。
新しいカテゴリCn
とLC
は、それぞれ未割り当てのコードポイントと大文字小文字のある文字を定義します。
これらは常にUnicodeによって定義されていましたが、Go1.25以前では誤って省略されていました。C
カテゴリは現在Cn
を含むため、すべての未割り当てのコードポイントが追加されています。
unique
unique
パッケージは、インターン化された値をより積極的に、効率的に、並列に回収するようになりました。その結果、Make
関数を使用するアプリケーションは、ユニークな値が多数インターン化された場合に、メモリ使用量の急激な増加が起きにくくなりました。
Handle
を含むMake
関数に渡された値は、ガベージコレクションでの回収時に、値の階層の深さに比例したサイクル数を要していました。Go1.25からは、未使用になると、1回のサイクルですぐに回収されます。
ports
Darwin
Go1.24のリリースノートに書かれていた通り、Go1.25はmacOS 12 Monterey以降をサポート対象とします。
Windows
Go1.25は、不具合のある 32ビットwindows/armポート(GOOS=windows
GOARCH=arm
)を含む最後のリリースです。Go1.26で削除される予定です。
Loong64
linux/loong64ポートは、race detector、runtime.SetCgoTraceback
を使用したCコードからのトレースバック情報の収集、および内部リンクモードでのcgoプログラムのリンクをサポートするようになりました。
RISC-V
linux/riscv64ポートでplugin
ビルドモードをサポートするようになりました。
GORISCV64
環境変数に新しい値rva23u64
を設定することで、RVA23U64プロファイルの命令セットを利用できるようになります。
Views: 0