Go Updates & Release Notes

Follow

73 updates curated from 86 sources by the Releasebot Team. Last updated: Oct 11, 2026

Get this feed:
  • Oct 8, 2026
    • Date parsed from source:
      Oct 8, 2026
    • First seen by Releasebot:
      Oct 11, 2026
    Google logo

    Go by Google

    [security] Vulnerabilities in golang.org/x/net

    Go releases golang.org/x/net v0.60.0 with key HTTP/2 security fixes, including protections against trailer-based memory exhaustion, excessive CPU use from repeated window updates, double flow control refunds, and an HPACK encoder race that could crash servers.

    Hello gophers,

    We have tagged version v0.60.0 of golang.org/x/net in order to address the following security issues:

    • net/http: HTTP/2 server memory exhaustion due to Trailer headers

    When "Trailer" headers are sent by a client, the HTTP server internally uses the header values to populate the Request.Trailer map passed to the server handler. Because Request.Trailer is a map, each entry incurs memory overhead. For HTTP/2 servers, a malicious client can exploit this by sending a "Trailer" header that declares a large number of fields, causing the server to allocate a disproportionate amount of memory while bypassing Server.MaxHeaderValueCount and Server.MaxHeaderBytes limits. This exploit is not applicable for HTTP/1 servers, which do not support multiplexing a large number of requests over one TCP connection, and whose Server.MaxHeaderBytes are calculated differently. Server.MaxHeaderValueCount and Server.MaxHeaderBytes limits are now applied towards the trailer fields declared in "Trailer" headers. Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue. This is CVE-2026-78659 and Go issue https://go.dev/issue/81857.

    • net/http: excessive CPU consumption from repeated initial window changes

    A malicious HTTP/2 peer could cause excessive CPU consumption in the client or server by opening a large number of streams and then sending many small SETTINGS frames containing SETTINGS_INITIAL_WINDOW_SIZE values. The HTTP/2 client and server now efficiently handle changes to the initial window size (O(1) rather than O(number of streams)). Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue. This is CVE-2026-78669 and Go issue https://go.dev/issue/81742.

    • net/http: double flow control refund on HTTP/2 server streams

    The HTTP/2 server could refund connection-level flow control twice for the same data: Once when a client resets a stream (refunding data for any sent-but-unread portion of the stream), and again when a request handler reads the buffered data. A malicious client could exploit this to bypass the configured connection-level flow control limit (MaxReceiveBufferPerConnection). Total buffered data is still limited by the concurrent stream limit and stream-level flow control. The HTTP/2 server now waits to refund connection-level flow control for reset streams until after the request handler is complete. Thanks to Ali Sherif (https://www.linkedin.com/in/ali-sherif-13812b276/) for reporting this issue. This is CVE-2026-78663 and Go issue https://go.dev/issue/81743.

    • net/http: HTTP/2 server crash due to HPACK encoder race

    HTTP/2 servers could end up crashing due to inadvertently modifying its HPACK encoder concurrently. This happens because the server modifies the HPACK encoder from two goroutines without synchronization: one uses the encoder to encode a HEADERS frame as part of a response sent to a client and the other modifies the encoder's table size when handling a SETTINGS frame containing SETTINGS_HEADER_TABLE_SIZE that a client sends. A malicious client can repeatedly send a request while changing the header table size to crash the server. Fix this issue by not applying SETTINGS_HEADER_TABLE_SIZE immediately. Instead, buffer any SETTINGS_HEADER_TABLE_SIZE received, and only apply the new value prior to the next time the server writes a frame. Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue. This is CVE-2026-97032 and Go issue https://go.dev/issue/81867.

    Cheers,

    Go Security team

    Original source
  • Oct 8, 2026
    • Date parsed from source:
      Oct 8, 2026
    • First seen by Releasebot:
      Oct 11, 2026
    Google logo

    Go by Google

    [security] Go 1.27.2 and Go 1.26.9 are released

    Go releases 1.27.2 and 1.26.9, delivering 15 security fixes that harden HTTP/2, HTTP/1, crypto/tls, html/template, cmd/go, and os against crashes, memory exhaustion, request smuggling, checksum bypasses, and other security issues.

    Hello gophers,

    We have just released Go versions 1.27.2 and 1.26.9, minor point releases.

    These releases include 15 security fixes following the security policy:

    • net/http: HTTP/2 server crash due to HPACK encoder race

      HTTP/2 servers could end up crashing due to inadvertently
      modifying its HPACK encoder concurrently. This happens because the
      server modifies the HPACK encoder from two goroutines without
      synchronization: one uses the encoder to encode a HEADERS frame as part
      of a response sent to a client and the other modifies the encoder's
      table size when handling a SETTINGS frame containing
      SETTINGS_HEADER_TABLE_SIZE that a client sends. A malicious client can
      repeatedly send a request while changing the header table size to crash
      the server.
      Fix this issue by not applying SETTINGS_HEADER_TABLE_SIZE immediately.
      Instead, buffer any SETTINGS_HEADER_TABLE_SIZE received, and only apply
      the new value prior to the next time the server writes a frame.
      Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue.
      This is CVE-2026-97032 and Go issue https://go.dev/issue/81867.

    • net/http: HTTP/2 server memory exhaustion due to Trailer headers

      When "Trailer" headers are sent by a client, the HTTP server internally
      uses the header values to populate the Request.Trailer map passed to the
      server handler. Because Request.Trailer is a map, each entry incurs
      memory overhead. For HTTP/2 servers, a malicious client can exploit this
      by sending a "Trailer" header that declares a large number of fields,
      causing the server to allocate a disproportionate amount of memory while
      bypassing Server.MaxHeaderValueCount and Server.MaxHeaderBytes limits.
      This exploit is not applicable for HTTP/1 servers, which do not support
      multiplexing a large number of requests over one TCP connection, and
      whose Server.MaxHeaderBytes are calculated differently.
      Server.MaxHeaderValueCount and Server.MaxHeaderBytes limits are now
      applied towards the trailer fields declared in "Trailer" headers.
      Thanks to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue.
      This is CVE-2026-78659 and Go issue https://go.dev/issue/81857.

    • crypto/tls: reject malformed ECH outer extension references

      Multiple ECH outer extension references are not
      permitted under RFC 9849; previously, a client
      could send a well-crafted packet that could
      trigger memory exhaustion in the server process
      by specifying multiple references.
      We now reject these as malformed and curb the
      memory amplification vector as a result.
      This is CVE-2026-97031 and Go issue https://go.dev/issue/81855.

    • cmd/go: checksum bypass for golang.org/fips140

      Previously, a user operating inside of a malicious
      Go project that defines a bogus golang.org/fips140
      and operates a malicious GOMODPROXY the user chooses
      to connect to can serve an arbitrary module in its
      place.
      We now unpack the trusted ziphash for the bundled
      golang.org/fips140 module and construct its entry
      in the GOMODCACHE such that it can be verified by
      the toolchain.
      This is CVE-2026-94444 and Go issue https://go.dev/issue/81833.

    • cmd/go: checksum database bypass for golang.org/toolchain

      Previously, a user operating inside of a malicious
      Go project that defines a bogus golang.org/toolchain
      go.sum entry and operates a malicious GOMODPROXY the
      user chooses to use can bypass the intended checksum.
      We now ensure that golang.org/toolchain always goes
      to the network for the canonical checksum.
      This is CVE-2026-94447 and Go issue https://go.dev/issue/81834.

    • html/template: reset context tracking on consecutive template expressions

      When a JavaScript template literal contains
      consecutive expressions, the context tracking
      state was not properly reset upon entering a
      new expression.
      We now ensure that template-literal expression
      entries correctly reset context variables so all
      subsequent regular expression literals are
      accurately recognized and escaped.
      This is CVE-2026-94448 and Go issue https://go.dev/issue/81821.

    • html/template: recognize yield as regexp preceder keyword

      A trusted template author may have previously
      written a valid template wherein the use of
      the yield keyword would not be correctly
      escaped.
      We now ensure that valid keyword uses are
      escaped and non-keyword uses are not escaped.
      This is CVE-2026-97030 and Go issue https://go.dev/issue/81823.

    • net/textproto, mime/multipart: memory limit bypass when parsing MIME headers

      Parsing a multipart form could bypass memory limits and read an
      arbitrarily long line into memory when the remaining limit at the
      start of a part was less than 400 bytes.
      Multipart form memory limits are now properly enforced in this situation.
      Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue.
      This is CVE-2026-94440 and Go issue https://go.dev/issue/81741.

    • net/http: HTTP/1 client connection desynchronization after CONNECT rejection

      When http.Transport sends an HTTP/1 CONNECT request with a non-empty
      Request.Body, it writes the body directly to the connection without
      framing after the request headers. If the server rejects the CONNECT
      request with a non-2xx keep-alive response, Transport returns the
      connection to the idle pool. Because CONNECT requests do not have a
      request body, the server may interpret the trailing body bytes as a
      subsequent pipelined HTTP/1.1 request on the connection, leaving the
      pooled connection desynchronized and causing the next caller that reuses
      it to read the response to the injected request. In reverse proxies
      (including httputil.ReverseProxy) that forward CONNECT requests through
      a shared Transport, this can lead to cross-user response poisoning.
      The HTTP/1 transport now closes a connection after sending a CONNECT
      request, regardless of the response status.
      In addition, ReverseProxy now rejects incoming CONNECT requests
      with a 405 Method Not Allowed response. ReverseProxy has never handled
      CONNECT requests in a useful fashion (it does not convert the
      connection into a bidirectional tunnel), so we do not expect this
      change to negatively affect any current users.
      Thanks to Xclow3n (Rajat Raghav) for reporting this issue.
      This is CVE-2026-56866 and Go issue https://go.dev/issue/81740.

    • net/http: HTTP/1 server connection desynchronization after 2xx CONNECT response

      When an HTTP server handler sent a 2xx response to an HTTP/1 CONNECT request
      and returned without hijacking the connection, the server improperly continued
      to read and serve requests from the connection. Since a 2xx response to an
      HTTP/1 CONNECT converts the connection into a tunnel, the server should not
      treat the connection as continuing to contain HTTP.
      The impact of this misbehavior is mostly limited to potential request smuggling,
      where an intermediate proxy considers the data on the connection to be tunneled
      and the server considers it to be HTTP.
      The HTTP/1 server now always closes a connection after responding to a CONNECT
      request, regardless of the response status.
      Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue.
      This is CVE-2026-94439 and Go issue https://go.dev/issue/81744.

    • net/http: excessive CPU consumption from repeated initial window changes

      A malicious HTTP/2 peer could cause excessive CPU consumption in the
      client or server by opening a large number of streams and then sending
      many small SETTINGS frames containing SETTINGS_INITIAL_WINDOW_SIZE values.
      The HTTP/2 client and server now efficiently handle changes to the
      initial window size (O(1) rather than O(number of streams)).
      Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue.
      This is CVE-2026-78669 and Go issue https://go.dev/issue/81742.

    • net/http: HTTP/2 transport accepts malformed framing-related headers

      Historically, we have been rather lax about malformed framing-related
      headers in our HTTP/2 implementation, as they cannot interfere with
      HTTP/2 framing. However, this makes it possible for our HTTP/2
      implementation to forward responses containing such headers to an HTTP/1
      client when acting as a reverse proxy. If the HTTP/1 client also does
      not behave strictly enough, this can result in response smuggling.
      We now delete malformed framing-related headers when received by our
      HTTP/2 transport, so they will not be forwarded to a potentially
      vulnerable HTTP/1 client.
      Thanks to TJ Barton for reporting this issue.
      This is CVE-2026-78660 and Go issue https://go.dev/issue/81115.

    • os: Root.Mkdir(All) can follow junctions out of the root on Windows

      On Windows, when the target of Root.Mkdir or Root.MkdirAll was a junction
      pointing to an empty location, the operation would create a directory at
      the junction target even when that target was located outside the root.
      This only applies to operations where the last path component is a
      junction (path/to/junction, but not path/junction/target).
      Root.Mkdir and Root.MkdirAll now correctly avoid resolving junctions.
      Thanks to Daniele Ballarini for reporting this issue.
      This is CVE-2026-56857 and Go issue https://go.dev/issue/81739.

    • net/http: lack of limit on size of parsed Range headers

      When parsing a Range header containing a large number of small ranges,
      FileServer(FS), ServeContent, and ServeFile(FS) could consume an excessive
      amount of CPU.
      These functions now ignore Range headers containing more than 200 ranges.
      The limit is controlled by the new httpservecontentmaxranges=
      GODEBUG setting. Setting GODEBUG=httpservecontentmaxranges=0
      disables the limit.
      Thanks to Jakub Ciolek (https://ciolek.dev) for reporting this issue.
      This is CVE-2026-78667 and Go issue https://go.dev/issue/81858.

    • net/http: double flow control refund on HTTP/2 server streams

      The HTTP/2 server could refund connection-level flow control twice for the same data:
      Once when a client resets a stream (refunding data for any sent-but-unread portion
      of the stream), and again when a request handler reads the buffered data.
      A malicious client could exploit this to bypass the configured connection-level
      flow control limit (MaxReceiveBufferPerConnection). Total buffered data is still
      limited by the concurrent stream limit and stream-level flow control.
      The HTTP/2 server now waits to refund connection-level flow control for reset
      streams until after the request handler is complete.
      Thanks to Ali Sherif (https://www.linkedin.com/in/ali-sherif-13812b276/) for reporting this issue.
      This is CVE-2026-78663 and Go issue https://go.dev/issue/81743.

    View the release notes for more information:
    https://go.dev/doc/devel/release#go1.27.2

    You can download binary and source distributions from the Go website:
    https://go.dev/dl/

    To compile from source using a Git clone, update to the release with
    git checkout go1.27.2 and build as usual.

    Thanks to everyone who contributed to the releases.

    Cheers,
    Dmitri and Michael for the Go team

    Original source
  • All of your release notes in one feed

    Join Releasebot and get updates from Google and hundreds of other software products.

    Create account
  • Oct 5, 2026
    • Date parsed from source:
      Oct 5, 2026
    • First seen by Releasebot:
      Oct 6, 2026
    Google logo

    Go by Google

    [security] Go 1.27.2 and Go 1.26.9 pre-announcement

    Go plans minor releases with private standard library security fixes for several CVEs.

    Hello gophers,

    We plan to issue Go 1.27.2 and Go 1.26.9 during US business hours on Thursday, October 8.

    These minor releases include PRIVATE security fixes to the standard library, covering the following CVEs:

    • CVE-2026-97032
    • CVE-2026-78659
    • CVE-2026-97031
    • CVE-2026-94440
    • CVE-2026-56866
    • CVE-2026-94439
    • CVE-2026-78669
    • CVE-2026-56857
    • CVE-2026-78667
    • CVE-2026-78663

    Following our security policy, this is the pre-announcement of those releases.

    Thanks,
    The Go team

    Original source
  • Oct 2, 2026
    • Date parsed from source:
      Oct 2, 2026
    • First seen by Releasebot:
      Oct 4, 2026
    Google logo

    Go by Google

    Arch-specific SIMD in Go

    Go adds experimental SIMD support for arm64 and wasm in Go 1.27, expanding the archsimd API beyond amd64. It brings clearer vector, mask, and type-conversion primitives for faster low-level code across supported architectures.

    Since Go 1.26, we have supported an experimental amd64 SIMD API. Now in Go 1.27, we support two more architectures: arm64 and wasm.

    The new APIs can be accessed by setting GOEXPERIMENT=simd when building a program. They are defined in the simd/archsimd package.

    archsimd is the lower-level infrastructure that simd builds on, essentially the intrinsics layer in other languages. For exotic operations that only exist on a specific architecture, users can access them by transitioning from simd to archsimd (via ToArch and <Types>FromArch). For details, please refer to the simd blog post.

    For readers with prior knowledge of SIMD intrinsics in other languages, you might find that our archsimd API does not directly mirror the underlying hardware instructions:

    • We give our APIs sensible names: e.g., instead of _mm512_slli_epi64, we just call it ShiftAllLeft.
    • We leave some architecture details to compiler optimizations rather than exposing them in the API: e.g., instead of _mm512_maskz_add_ps(m, x, y), we optimize x.Add(y).Masked(m) into the same instruction.

    These design decisions make our APIs smaller and more accessible, and they also happily make the simd implementation much easier.

    For readers without prior knowledge of SIMD intrinsics, we hope our low-level API is a natural and pleasant journey for you.

    Please share your feedback and comments. Anything about usability, performance, etc., is appreciated. The parent issue for this project is #73787.

    What is SIMD

    SIMD stands for Single Instruction, Multiple Data. SIMD instructions operate on wide registers (128-bit, 256-bit, or more) containing multiple 8- to 64-bit elements, performing operations across all elements in parallel. Wider registers and parallel execution provide a significant performance boost to algorithms that can take advantage of them.

    Until now, anyone who wanted to use SIMD in Go had to endure the friction of writing assembly language. The new archsimd package is here to change that.

    Goals

    The goal is to support as many SIMD instructions across different architectures as possible. Currently, we have amd64, arm64, and wasm available. Our amd64 support has the largest API surface, covering AVX, AVX2, and many AVX-512 extensions. Our arm64 support currently covers NEON, with SVE and some SVE2 already on the way. Our wasm support is also mostly complete, thanks to its well-defined 128-bit SIMD abstraction.

    Some users might be interested in matrix extensions on certain architectures, such as AMX and SME. We haven’t fully settled on how to represent matrices effectively in Go, so they are not yet supported, but we might support them in the future.

    API Design and Naming

    Types

    The architecture-specific SIMD API is imported from simd/archsimd.

    archsimd uses distinct struct types, such as Float32x4, Int32x8, or Uint8x16, to signal the shape and element type of each vector, and defines operations as methods on those types. At this moment, archsimd supports only fixed-width vector extensions. Scalable vector extensions like arm64 SVE and RVV will have different struct types to represent vectors. Mask types also come with vector-like shapes, e.g., Mask32x4.

    Methods

    Across different vector widths, element types, and architectures, we use the same method name whenever operations are semantically identical:

    • Regardless of vector width or architecture, element-wise addition is simply x.Add(y); the type of x determines which instruction to emit. Instead of 18 different function names for addition, there is only one method name.
    • When instructions on different architectures look similar at a glance but differ in edge-case behavior, we give them distinct names so differences don’t silently bite you. For example, 16-byte table lookup on amd64 (VPSHUFB) zeros the output byte when the index is negative (index < 0) and wraps modulo 16 otherwise, so we call it PermuteOrZero. On arm64 NEON (VTBL) and wasm (i8x16.swizzle), any out-of-range index (index < 0 || index >= 16) zeros the output byte, so we call it LookupOrZero.
    • On amd64, many 256-bit and 512-bit instructions operate independently within 128-bit lanes rather than across the entire register. We explicitly suffix those methods with Grouped (such as InterleaveLoGrouped or PermuteOrZeroGrouped) to make the 128-bit lane boundary obvious.

    Methods require a receiver value, which doesn’t work for creating a vector from memory or a scalar. For those, archsimd provides package-level functions named with the target vector type:

    • Slices (the default): In Go 1.27, loading and storing slices use the shortest names: archsimd.LoadFloat32x4(s []float32) Float32x4 and x.Store(s []float32). For tail elements that may be shorter than a full vector, archsimd.LoadFloat32x4Part(s []float32) (Float32x4, int) zero-fills the remaining lanes and returns the number of elements loaded, paired with x.StorePart(s []float32) int.
    • Arrays and Broadcasts: Fixed-size array pointers use the Array suffix (archsimd.LoadFloat32x4Array(y *[4]float32) and x.StoreArray(y *[4]float32)), and archsimd.BroadcastFloat32x4(v float32) broadcasts a scalar to all lanes.

    Type Reinterpretation

    Reinterpretations are type casts without any cost. SIMD algorithms frequently reinterpret bits across element types and widths.

    In the Go 1.26 experiment, we implemented this with As methods, which suffered from a quadratic explosion of type pairs and couldn’t generalize to width-agnostic vectors in simd or SVE.

    In Go 1.27, we replace them with composable zero-cost conversions:

    • ToBits() reinterprets a signed integer or float vector as an unsigned integer vector of the same element width (e.g., Int32x4.ToBits() -> Uint32x4), and BitsToInt32() / BitsToFloat32() converts back.
    • ReshapeToUint<W>s() on unsigned vectors changes the element width within the same register width. For example, if x is an archsimd.Uint8x16, then x.ReshapeToUint32s().BitsToFloat32() reinterprets the bits of x as an archsimd.Float32x4 at zero runtime cost.

    Masks

    Different architectures encode vector masks very differently, e.g. k mask registers on AVX-512, full vector bitmasks on AVX/AVX2, NEON, and wasm, and predicate registers on SVE. To hide this hardware detail, archsimd provides opaque Mask types (such as Mask32x4) matching each vector shape:

    • Comparisons like x.Greater(y) produce a Mask.
    • x.Masked(m) zeros elements where m is false, and x.IfElse(m, y) (which replaces Merge from Go 1.26) selects elements from x where m is true and from y where m is false.
    • The compiler peepholes mask operations with the surrounding instructions: on AVX-512, x.Add(y).Masked(m) or x.Add(y).IfElse(m, z) compiles into a single zero-masked or merge-masked VPADD instruction; on AVX2, NEON, or wasm, it lowers to the appropriate bitwise AND or blend/bitselect instruction.

    Examples

    Portable algorithms like inner product can easily be implemented using the portable simd package, as shown in the companion simd blog post. However, we still expose archsimd to tap into exotic, architecture-specific instructions that do not fit into a portable intersection API, or instructions that can simply do things faster than what simd provides.

    On amd64, the GFNI extension exposes GaloisFieldAffineTransform operations. Putting aside what a Galois Field is, these operations do a simple thing:

    // Each element of A is interpreted as a matrix of 8 rows of vectors of 8 bits.
    // Each element of x is interpreted as a vector of 8 bits.
    // The b argument is likewise a vector of 8 bits.
    // The result is z[i] = (A[i/8] * x[i]) + b.
    //
    // The matrix * and vector + follow the usual rules for linear algebra,
    // but based on AND and XOR for scalar * and +
    //
    // Asm: VGF2P8AFFINEQB, CPU Feature: AVX512GFNI
    func (x Uint8x16) GaloisFieldAffineTransform(A Uint64x2, b uint8) Uint8x16
    

    Each 8x8 bit matrix A is packed row-by-row into a single uint64. Because any linear combination or permutation of the 8 bits within a byte can be written as an 8x8 bit matrix, this single instruction is a Swiss Army knife for byte-level bit manipulation.

    For example, reversing the bit order of every byte (bits.Reverse8) normally requires nibble lookup tables, masks, shifts, and ORs in SIMD. With GaloisFieldAffineTransform, we can simply multiply each byte by the 8x8 anti-diagonal identity matrix (0x8040201008040201) to reverse all 8 bits of 64 bytes at a time in a single instruction.

    Another example is matrix transpose. On amd64, the permutation instructions are shaped in a non-portable way, so using simd is cumbersome and might incur emulations. An efficient implementation can be written more directly in archsimd. The example below transposes an 8-by-8 matrix of 32-bit integers in registers on amd64 using AVX2’s 128-bit lane-grouped interleaves (InterleaveLoGrouped, InterleaveHiGrouped) and cross-lane permutations (ConcatPermuteScalarsGrouped, ConcatPermute128Scalars).

    Good Practices

    When walking through the examples above, you might have a few questions:

    • What is archsimd.X86.AVX512GFNI(), and can I omit it?
    • Why is the strided loop written as i = 0; i < len(src)-v.Len()+1; i += v.Len(), instead of i = 0; i + v.Len() <= len(src); i += v.Len()?
    • Why does Transpose8 take 8 vector parameters rather than a struct or an [8]archsimd.Int32x8 array?

    At first glance these choices might look like minor stylistic preferences, but each of them is chosen for an important performance or correctness reason:

    • CPU feature checks (archsimd.X86., archsimd.ARM64.)
      On amd64, we provide runtime feature checks like archsimd.X86.AVX(), AVX2(), AVX512(), and extension checks like AVX512GFNI() or AVX512VNNI(); on arm64, NEON is always available, and we provide checks for optional extensions like archsimd.ARM64.PMULL(), SVE(), and SVE2(). The compiler doesn’t know ahead of time whether the machine running your binary supports optional SIMD extensions. If you don’t guard your SIMD code with the appropriate feature check, your program may crash with SIGILL on hardware that lacks the instruction.
      Just as importantly, CPU feature checks act as compiler optimization hints. For example, AVX-512 supports hardware merge-masking on instruction outputs. How the compiler lowers x.Add(y).IfElse(m, z) on a 128-bit or 256-bit vector depends on which CPU features are known to be available. If the code is not guarded by archsimd.X86.AVX512(), the compiler must conservatively emit a vector VPADD followed by a VPBLEND instruction. Inside an if archsimd.X86.AVX512() block, however, the compiler knows AVX-512 is available and fuses the sequence into a single merge-masked AVX-512 VPADD instruction.
    • Bounds check elimination in strided loops
      How you write the loop bound determines whether the compiler’s prove pass can eliminate slice bounds checks inside the loop. In i + v.Len() <= len(src), the addition i + v.Len() could theoretically overflow to a negative int if len(src) were near math.MaxInt, which prevents the compiler from proving that i is always non-negative and in-bounds. Writing i < len(src)-v.Len()+1 avoids that potential overflow, allowing the loop body to compile with zero bounds checks.
    • Keeping vectors in registers (avoiding large composite types)
      Transpose8 passes 8 vector parameters rather than a struct of 8 fields or an [8]archsimd.Int32x8 array because Go’s ABI and SSA backend currently place large composite types in memory rather than in registers (a known issue tracked at #24416). Because SIMD vectors are 16 to 64 bytes each, spilling them to the stack hurts performance much more than spilling scalar values. This applies to both function parameters and local variables, so avoid wrapping SIMD vectors inside large arrays or structs in hot loops. There are ongoing efforts to promote composite memory accesses back into registers, which have not yet landed in Go 1.27.

    Trying it out

    In Go 1.27, GOEXPERIMENT=simd supports amd64 (AVX, AVX2, and AVX-512), arm64 (NEON), and wasm (WebAssembly 128-bit SIMD) out of the box. Whether you are on an Intel/AMD machine, an arm64 server or Apple Silicon Mac (M1/M2/M3/M4), or targeting WebAssembly, you can try archsimd natively right away:

    GOEXPERIMENT=simd go test simd/archsimd/...
    

    You can also cross-test wasm (or amd64 via Rosetta emulation on Apple Silicon) by setting GOARCH:

    # Run wasm SIMD tests using a WASI runtime:
    GOOS=wasip1 GOARCH=wasm GOEXPERIMENT=simd go test simd/archsimd/...
    
    # Or run amd64 AVX2 tests on Apple Silicon via Rosetta:
    GOARCH=amd64 GOEXPERIMENT=simd go test simd/archsimd/...
    

    We’re interested in all sorts of feedback! Early users have already helped us catch bugs (such as #77582) and identify places where code generation or API ergonomics could be improved. We tried hard to pick clear, consistent names and cover the most useful instructions, but archsimd is a massive API surface and there is always room to improve.

    Future work

    For Go 1.28 and beyond, we are actively working on completing arm64 SVE and SVE2 support in archsimd (introducing width-agnostic scalable vector types like archsimd.Float32s backed directly by hardware SVE registers and predicates) and wiring it into simd. We also plan to expand archsimd to additional architectures such as riscv64, ppc64, s390x, and loong64, improve register promotion for composite types, and continue filling in instructions and compiler optimizations based on community feedback.

    Original source
  • Sep 24, 2026
    • Date parsed from source:
      Sep 24, 2026
    • First seen by Releasebot:
      Sep 25, 2026
    Google logo

    Go by Google

    Platform-independent SIMD in Go

    Go introduces an experimental portable SIMD package that brings near-assembly performance to vectorized code across amd64, arm64, and wasm. It adds a platform-agnostic API, emulation for unsupported targets, and a simpler path for high-performance data processing.

    Go 1.26 and 1.27 include experimental APIs for Single Instruction Multiple Data (SIMD) operations.

    SIMD is a native feature of many modern CPUs that allows software to perform uniform operations across vectors of data very quickly, such as adding 8 pairs of float64 values in a single instruction. It can significantly speed up many computationally-intensive tasks, ranging from cryptography to data processing to AI. In fact, Go’s Green Tea garbage collector even makes use of SIMD to accelerate scanning memory for live objects.

    Prior to these new experimental APIs, the only way to access this functionality from Go was by writing Go assembly. This was only worth it for truly performance-critical compute kernels, which meant plenty of software that could benefit from SIMD simply left a lot of the CPU unused.

    Go 1.26 introduced a SIMD API for amd64, and Go 1.27 added APIs for arm64 (specifically NEON) and wasm. However, a basic challenge for a SIMD API is the enormous variation between platforms, not simply in what operations they support, but even in how vectors are represented. Some platforms provide fixed-size vectors, typically between 128 bits and 512 bits, while on others the vector size isn’t known at build time and must be queried when the program starts. To provide full access to the breadth of these platforms, these APIs live in an architecture-dependent archsimd package.

    But Go 1.27 goes beyond these architecture-dependent APIs and introduces an experimental, fully portable, platform- and size-agnostic SIMD interface, loosely based on Highway for C++. The goal is to support write-once near-asm-performance “simd” code on platforms with SIMD support, and to provide a competent emulation on those platforms that do not (yet) have SIMD support. The simd package currently supports AVX, AVX2, and AVX512 on amd64, NEON on arm64, and wasm’s SIMD instructions.

    Motivation: variation among SIMD architectures

    SIMD architectures vary in several dimensions. Some provide a single fixed vector size (wasm, PowerPC, and s390x, 128 bits). Some provide several fixed vector sizes (amd64, with 128, 256, and 512; loong64 with 128 and 256). Riscv64 supports vectors of unspecified size between 128 and 65536 bits, though the length is limited to powers of 2. Arm64 supports one fixed size (128 bits, NEON), and one variable size (128-2048 bits, powers of two only, SVE). On a given instance of a particular architecture, determining what sizes that particular instance happens to support requires feature checks: amd64, but is it AVX, AVX2, or AVX512? Arm64, but is it NEON or SVE? If SVE, how large? Which variant of SVE: SVE, SVE2, or SVE2.1?

    Different SIMD architectures vary in how they handle vector masking. For vectors, if-then-else across a vector can be implemented with masks; do the operation, but only assign the result (or load, or store) where the mask is “true”. Some SIMD variants do not provide masks; all operations work across all elements, and “masking” is done with vector bitmasks and vector boolean operations (wasm, AVX, AVX2, NEON). Some provide special mask registers, with one bit governing operations on one vector element (AVX512 and RVV). Others (SVE) allocate one bit per vector byte, but the least-significant bit of each element’s mask bits governs masked operations. AVX2 also supports masked loads and stores, but using a plain vector as the mask, and with the most-significant bit governing the operation.

    A third source of variation is in the operations themselves. Each architecture provides its own primitives for rearranging vector elements; some require constant inputs, others support variable inputs. Different SIMD architectures support different crypto-related operations. Even basic arithmetic can have varying support; for example wasm lacks comparisons for vectors of 64-bit integers. Even for a given vector length on a particular architecture, instruction support depends on “features” that must be checked.

    Even though Go’s architecture-dependent archsimd package was designed to be as uniform as possible across architectures, many of these quirks remain, and make designing, writing, and testing code for multiplatform SIMD onerous. We could do more in the archsimd package to make the different architectures appear more similar, but we can only go so far without compromising efficiency.

    Overview

    The new simd package hides these differences by removing fixed-size vectors from the type system, and by only supporting those operations that are in the intersection of all the different platforms, and fills gaps in the intersection with efficient emulation in terms of other SIMD instructions. The goal is a set of operations that is:

    1. adequate to support many data processing algorithms that benefit from a vectorized implementation (but are not tied to a particular vector size),
    2. is as efficient as assembly language when the source code operations match the underlying hardware,
    3. is otherwise emulated as well as possible,
    4. and is easy to read and understand (even/especially if an LLM ends up writing the code).

    On platforms that lack SIMD instructions or that lack support in archsimd, all of the operations are emulated, so that code written using the simd package will always run.

    To use this experimental package, set GOEXPERIMENT=simd at build time, just like using the experimental archsimd package.

    The simd vector types are just capitalized, plural, primitive types, for example simd.Uint8s or simd.Float32s. Vectors are loaded from and stored to slices, for example:

    // innerProduct returns the inner product of x and y.
    func innerProduct(x, y []float32) float32 {
        var a simd.Float32s
        var i int
        for i = 0; i < len(x)-a.Len()+1; i += a.Len() {
            u := simd.LoadFloat32s(x[i : i+a.Len()])
            v := simd.LoadFloat32s(y[i : i+a.Len()])
            a = u.MulAdd(v, a)
        }
        if i < len(x) {
            u, _ := simd.LoadFloat32sPart(x[i:])
            v, _ := simd.LoadFloat32sPart(y[i:])
            a = u.MulAdd(v, a)
        }
        return sum(a)
    }
    // sum returns scalar sum of elements of x.
    func sum(x simd.Float32s) float32 {
        s := make([]float32, x.Len())
        x.Store(s)
        var r float32
        for _, e := range s {
            r += e
        }
        return r
    }
    

    This example also shows one of the limitations of the first experimental release of this package; because there’s no common way to sum across all the elements of a vector, it’s not supported by simd in Go 1.27, though ReduceSum will appear in the next release so sum can be replaced with just simd.ReduceSum.

    SIMD comparisons produce mask values, which are specific to the corresponding vector element width, so that comparisons of Int8s produce Mask8s, etc., and mask values can be used to select and filter vectors.

    [The page continues with detailed tables of supported operations, examples of transitioning between platform-specific and portable SIMD code, GODEBUG settings to control SIMD behavior, implementation details about compiler AST rewriting for SIMD, and plans for future releases including adding SVE support and more SIMD operations in Go 1.28.]

    Original source
  • Similar to Go with recent updates:

  • Sep 16, 2026
    • Date parsed from source:
      Sep 16, 2026
    • First seen by Releasebot:
      Sep 17, 2026
    Google logo

    Go by Google

    Size-Specialized Memory Allocation

    Go 1.27 improves allocation-heavy performance with faster small memory allocations, especially under 80 bytes. The runtime adds size-specialized malloc paths that speed up common 16 and 24 byte allocations, with fallback support and an option to disable the experiment if needed.

    Go 1.27 includes faster memory allocation for allocations of fewer than 80 bytes.

    Allocations can be up to 20-30% faster, making allocation-heavy programs up to 1% faster. The Go runtime improves the performance of those allocations by adding specialized functions that are used to allocate certain sizes. These specialized functions can then make certain assumptions that make them faster and easier to optimize. This blog post will explain how this works and how it makes your programs faster.

    Heap allocations are created by the runtime’s mallocgc function, which requires the size of the allocation and whether it contains pointers. When the compiler determines that an object escapes to the heap or otherwise needs to be dynamically allocated, it inserts a call to newobject, which is a simple wrapper function that extracts the size of the object and whether it contains pointers and passes those to mallocgc.

    These two pieces of information determine most of the work that the allocator needs to do. The size is important because the allocator defines ranges of sizes called “size classes”. For most allocations that are not too large and not too small, it will return a block of memory from a list of free objects that are all sized to the maximum size of the size class. So, for instance, size class 3 is 17-24 bytes. So whether you allocate 17 bytes or 24 bytes, the allocator will give you the next free 24 byte object available in its list of 24 byte objects. Below is a table of the size ranges of each of the size classes up to 80 bytes. There are separate sets of free lists, which we call spans, depending on whether the allocation has pointers, because of the bookkeeping we need to do for the garbage collector.

    Size class | Range of sizes
    1 | 1-8 bytes
    2 | 9-16 bytes
    3 | 17-24 bytes
    4 | 25-32 bytes
    5 | 33-48 bytes
    6 | 49-64 bytes
    7 | 65-80 bytes

    Because the size class and whether the allocation contains pointers determine which span we allocate from, the allocator has a type called the span class, whose value encodes both: it’s defined as sizeClass<<1 | noPointers. When implementing size-specialized malloc it was clear that it made the most sense to specialize on these span classes because much of the behavior of the allocator was determined by the span class.

    We generate a specialized mallocgc variant for every span class. For instance, the function that allocates pointer-free objects in size class 3 is called mallocgcSmallNoScanSC3. Small means not tiny or large, NoScan means it has no pointers, and SC3 means size class 3 (17-24 bytes). Specialized functions are designed to be as simple as possible and cannot handle every corner case during allocation. When they detect such a case, such as when the GC is active, they fall back to a more generic allocation routine.

    So we end up with a new specialized mallocgc function for the tiny case (always no pointers) and one for each non-tiny span class: the non-pointer spans of size class 2 and above, and the pointer spans of size class 1 and above. These specialized mallocgc variants themselves are faster than calling mallocgc, but the benefits of specializing decrease as the sizes get larger: the allocation often gets dominated by needing to clear the memory, and at some point the rest of the work of allocation becomes negligible. And it’s not enough to just be faster than mallocgc! With size-specialized allocation, when the compiler knows which span class it needs to allocate for, it can directly insert a call to the specialized function instead of the call to newobject. But the compiler often doesn’t know which span class is being allocated when code is generated: think slices of dynamic length. Since the compiler can’t determine the size of the allocation, it will keep the call to mallocgc, and mallocgc itself has to determine whether a specialized function is available, which one it is, and then needs to call it. So the performance of the specialized function has to be high enough that even with the overhead of a dynamic call it’s still faster.

    This overhead issue isn’t the only problem. If it were, then we could create larger specialized functions, and have them reserved for the compiler to insert them when the size is known at compile-time. And if we didn’t call them dynamically we wouldn’t have to pay the dynamic overhead. But each specialized function that’s added increases the sizes of the executables produced by the compiler, and, more importantly, takes up precious instruction cache space. The single mallocgc function is often in the instruction cache because of how frequently allocations happen. If we have too many specialized functions and they’re not available in the cache, the overhead to retrieve the specialized code into the cache can cancel out any benefits. And the more specialized allocation code that’s in the icache, the more it crowds out the user code, making it slower to fetch and run user code. Doing a bunch of benchmarks stopping at different size classes, we determined that stopping at 80 bytes was the sweet spot.

    Of course, adding more specialized functions means more code to maintain. If each function were hand-written, the code in the specialized functions could easily drift apart and go out of sync. To help with this, we broke out the common parts of the specialized functions and wrote an inliner using the standard library go/ast package to parse and format and the golang.org/x/tools/go/ast/astutil package to manipulate the ASTs. The common parts of the functions are all written in standard Go code that is built and typechecked with the rest of the runtime to allow our tools to catch issues, but they are mostly just stubs for the inliner.

    So we were able to measure improvements in the size-specialized allocation functions, but why are they actually faster? The most apparent optimization is in clearing memory. The memory returned by mallocgc does not always need to be zeroed, but it often does, and doing so can often take up most of the time of the allocation. The memory clearing function memclrNoHeapPointers is written in highly-optimized assembly, but we could do better for the smaller clears. In a specialized function, if the size of the clear is constant, the compiler can replace calls to memclrNoHeapPointers with code to directly produce the instructions to clear the memory. The allocation can then skip a function call and some branches. This makes a difference for the really small allocations, but as they get bigger, the function call overhead becomes negligible.

    While faster memory clearing provides the biggest improvement, there are some other tricks that are also possible in the specialized functions: Since they are specialized per span-class, the function doesn’t need to calculate the span class when retrieving the span. And because the size of the allocation is a constant, the compiler is able to do some optimizations to speed up the bookkeeping necessary for the allocation. One such case is with marking where the pointers are in the allocated memory. The specialized functions could also manually inline several of its helper functions. The go compiler can inline code, but it avoids inlining functions that it considers too large. We can override that in the generated code by inserting the function bodies into the callers. With the generator we can produce copies of each of the bodies without needing to worry about each of the copies drifting. And we could move code that handled less common cases, such as the runtime debugging flags, into the slow path functions to make the specialized functions smaller.

    While we hope this explanation of size-specialzed allocation is interesting, you as a Go programmer don’t need to think about any of this when writing your code. Memory allocations will just be a little faster, with the biggest benefits going to some of the most common allocations sizes, especially the 16 and 24 byte allocations. These allocations are some of the most common because they consist of two or three 64-bit values, so they include allocations for things such as interface values and strings which have two values, or slices which have three. We spent a lot of time tuning the behavior of size specialized malloc and making sure the impact of the instruction cache effects will be minimal: we were originally planning to release size-specialized allocation in Go 1.26 but decided to wait an extra release to do extra tuning and cut down the additional code size as much as we could.

    All you need to do to get the improved performance from size specialized allocations in your programs is to build them with Go 1.27. If you’re interested in more concrete actions you can take to improve memory allocation and garbage collection performance, please read the Go Garbage Collector Optimization Guide.

    Although we are confident that size-specialized allocation should not cause regressions in your code, if necessary, you can build your programs using GOEXPERIMENT=nosizespecializedmalloc to disable it. If you do need to do this to solve an issue you’re experiencing with size-specialized allocation, please file an issue at go.dev/issue/new so we can investigate it.

    Original source
  • Sep 2, 2026
    • Date parsed from source:
      Sep 2, 2026
    • First seen by Releasebot:
      Sep 3, 2026
    Google logo

    Go by Google

    [security] Vulnerabilities in golang.org/x/crypto

    Go tags golang.org/x/crypto v0.56.0 with security fixes for ssh, preventing denial-of-service deadlocks on established and undecided channels by handling or dropping unexpected messages instead of buffering and blocking the connection.

    Howdy gophers,

    We have tagged version v0.56.0 of golang.org/x/crypto in order to address the following security issues:

    ssh: prevent DoS on deadlocked established channel

    Previously, after a channel has been established, a malicious peer could send crafted messages that would deadlock the entire connection.

    Now, we handle all RFC 4254 channel messages; global requests are handled explicitly. Then, treat all other messages as a protocol error and tear the connection down instead of buffering and blocking.

    Thanks to Will Mortensen for reporting this issue.
    This is CVE-2026-56855 and Go issue https://go.dev/issue/81317.

    ssh: prevent DoS on deadlocked undecided channel

    Previously, a channel registered in the mux's chanList is not usable until it is established. A malicious peer was able flood the channel's incomingRequests, deadlocking the entire connection.

    Now, we add an atomic established state, set when a channel becomes usable. Until such a time, handlePacket drops every packet other than the open confirmation/failure, without blocking and without tearing down the connection.

    Thanks to Will Mortensen for reporting this issue.
    This is CVE-2026-78662 and Go issue https://go.dev/issue/81316.

    Cheers,
    Go Security Team

    Original source
  • Sep 2, 2026
    • Date parsed from source:
      Sep 2, 2026
    • First seen by Releasebot:
      Sep 3, 2026
    Google logo

    Go by Google

    Goroutine Leak Profiles

    Go introduces a goroutine leak profiler that helps developers find leaked goroutines in running programs, including production systems. The article shows how it surfaces blocked sends and other leak patterns, explains its low-false-positive approach, and outlines limits and fixes.

    Example: concurrent workers

    Consider a function that processes work items concurrently:

    type result struct {
        res workResult
        err error
    }
    
    func processWorkItems(ws []workItem) ([]workResult, error) {
        // Process work items in parallel, aggregating results in ch.
        ch := make(chan result)
        for _, w := range ws {
            go func() {
                res, err := processWorkItem(w)
                ch <- result{res, err}
            }()
        }
    
        // Collect the results from ch, or return an error if one is found.
        var results []workResult
        for range len(ws) {
            r := <-ch
            if r.err != nil {
                // This early return may cause goroutine leaks.
                return nil, r.err
            }
            results = append(results, r.res)
        }
        return results, nil
    }
    

    Because ch is an unbuffered channel, each worker goroutine blocks when sending its result until the main goroutine receives from the channel. If processWorkItems returns early due to an error, the receiving loop terminates, and all remaining sender goroutines block forever.

    This example is emblematic of a common mistake discovered in real Go programs, including Uber production services. Let’s see how we can find these leaks by using the new goroutine leak profiler.

    Debugging with the goroutine leak profiler

    The profile is available through the runtime/pprof package, as the goroutineleak profile type, or by installing the profile handlers defined by the net/http/pprof package. If you already have net/http/pprof set up in your service, then you don’t need to do anything else! The profile will be automatically made available for collection at the /debug/pprof/goroutineleak endpoint on whatever host and port the handlers are installed.

    [Example program and usage instructions omitted for brevity]

    Collecting the profile

    It won’t take long for the program to start accumulating leaks, which you can then view by using the web UI at http://localhost:6060/debug/pprof.

    Alternatively, you can collect the goroutine leak profile using curl, and then examine it with go tool pprof.

    The profile reveals the goroutines leaked at ch <- result{res, err} (line 33), pinpointing the culprit operation. Notably, the longer the program is running, the larger the number of leaked goroutines.

    Addressing the leak

    This leak can be simply fixed by giving ch a buffer:

    ch := make(chan result, len(ws))
    

    This allows all the work item goroutines to send a message without blocking in the event of a premature return of processWorkItems.

    Implementation

    The article explains the core concept of leak detection based on liveness of goroutines and how the Go runtime garbage collector is adapted to detect leaked goroutines by marking only unblocked goroutines as live and iteratively marking others reachable from them.

    Limitations

    The garbage collector based leak detection has limitations such as memory overreach (if concurrency primitives are reachable from global variables or runnable goroutines, leaks may not be detected), non-standard blocking (only Go first-class concurrency primitives are considered), and non-determinism (leaks can only be detected after occurrence).

    Performance impact

    Leak detection adds some overhead, especially in pathological cases, but is designed to minimize impact and can be tuned for profiling frequency.

    Acknowledgements

    Goroutine leak detection is the result of a research collaboration between Aarhus University, Washington University in St. Louis, and Uber, presented in “Dynamic Partial Deadlock Detection and Recovery via Garbage Collection” (Saioc et al., ASPLOS 2025). Transition to a Go feature was guided by members of the Go team at Google.

    Additional examples

    The article provides multiple real-world examples of goroutine leaks and how the goroutine leak profiler can detect them, including common patterns like double sends on channels, early returns causing blocked sends, timeouts with context cancellation, range over channels without closing, method contract violations, missing unlocks, unexpected channel operation orderings, mutual blocking between channels and mutexes, and misuse of sync.WaitGroup.

    Each example includes code snippets illustrating the leak and how the profiler highlights the issue, along with suggested fixes.

    Original source
  • Sep 1, 2026
    • Date parsed from source:
      Sep 1, 2026
    • First seen by Releasebot:
      Sep 2, 2026
    Google logo

    Go by Google

    Go 1.27.1 and Go 1.26.8 are released

    Go releases 1.27.1 and 1.26.8 minor point updates.

    Hello gophers,

    We have just released Go versions 1.27.1 and 1.26.8, minor point releases.

    View the release notes for more information:

    https://go.dev/doc/devel/release#go1.27.1

    You can download binary and source distributions from the Go website:

    https://go.dev/dl/

    To compile from source using a Git clone, update to the release with

    git checkout go1.27.1
    

    and build as usual.

    Thanks to everyone who contributed to the releases.

    Cheers,

    Michael and David for the Go team

    Original source
  • Aug 27, 2026
    • Date parsed from source:
      Aug 27, 2026
    • First seen by Releasebot:
      Aug 28, 2026
    Google logo

    Go by Google

    [security] golang.org/x/crypto fix pre-announcement

    Go plans a security fix for golang.org/x/crypto/ssh to address two CVEs.

    Hello gophers,

    We plan to issue a security fix for the package golang.org/x/crypto/ssh in the golang.org/x/crypto module during US business hours on Wednesday, September 2.

    This will cover the following CVEs:

    • CVE-2026-56855
    • CVE-2026-78662

    Following our security policy, this is the pre-announcement of the fix.

    Thanks,
    The Go team

    Original source
  • Aug 26, 2026
    • Date parsed from source:
      Aug 26, 2026
    • First seen by Releasebot:
      Sep 3, 2026
    Google logo

    Go by Google

    Generic Methods

    Go adds generic methods in Go 1.27, making type-parameterized code more ergonomic and readable. The update lets developers keep mapping and other reusable logic close to their types, with cleaner left-to-right method chains and better code organization.

    Generics was a profound change for Go—it fundamentally expanded the kinds of programs that gophers could write by adding type parameters to the language.

    One could now express generic types and functions in Go. These constructs decreased the need for specialized data types and functions, reducing program verbosity and improving the ergonomics of the language in those cases.

    To illustrate, different kinds of linked lists could now be condensed into a single type definition:

    // before Go 1.18
    type ListOfInts struct {
        elem int
        next *ListOfInts
    }
    type ListOfStrings struct {
        elem string
        next *ListOfStrings
    }
    // ...
    
    // after Go 1.18
    type List[E any] struct {
        elem E
        next *List[E]
    }
    

    Likewise, sorting different kinds of ordered data could be expressed as a single function:

    // before Go 1.18
    func SortInts(s []int) { /* ... */ }
    func SortStrings(s []string) { /* ... */ }
    // ...
    
    // after Go 1.18
    func Sort[E cmp.Ordered](s []E) { /* ... */ }
    

    However, no such capability came to methods.

    The generics proposal reasoned that because generic interface methods are difficult to implement efficiently (discussed later), it didn’t make sense to add type parameters to non-interface (or “concrete”) methods either. In that view, methods are primarily the means of implementing an interface.

    Go 1.27 takes a different view and consequently adds generic methods to Go. In this post, we’ll explain this change of view and demonstrate some uses of this new feature.

    Methods for organization

    Methods enable organizing functionality around types. To illustrate, let’s reconsider the linked list from above (adding some conveniences):

    type List[E any] struct {
        elem E
        next *List[E]
    }
    func NewList[E any](elems ...E) List[E] { /* ... */ }
    func (List[E]) String() string { /* ... */ }
    

    Suppose that one wanted to map this structure to hold a value of some other type, like a string. A method like ToString would do:

    func (List[E]) ToString(f func(E) string) List[string] { /* ... */ }
    

    By providing a “transform” function f, ToString can be customized with “off-the-shelf” routines.

    For example, strconv.Itoa might work for a List[int]:

    func main() {
        fmt.Println(NewList(1, 2, 3).ToString(strconv.Itoa)) // [1 2 3]
    }
    

    For a List[[]byte], more options come to mind (depending on the use case):

    func main() {
        l := NewList([]byte("Hallo Welt"), []byte("Helló világ"))
        fmt.Println(l.ToString(hex.EncodeToString))                 // [48616c6c6f2057656c74 48656c6cc3b32076696cc3a167]
        fmt.Println(l.ToString(base64.StdEncoding.EncodeToString))  // [SGFsbG8gV2VsdA== SGVsbMOzIHZpbMOhZw==]
    }
    

    Note that parameterizing List allowed generalization of the source type, but not the destination type, since that depends on the transformation being applied. This might be reasonable with just a single destination type, but what if there were many?

    In Go 1.18, a generic function could be used for this:

    // after Go 1.18
    func MapList[E, R any](l List[E], f func(E) R) List[R] { /* ... */ }
    

    But using a function has the disadvantage of moving MapList into the package scope—if many data types support mapping operations, things could get crowded. Furthermore, chained calls must be written “inside out”:

    func main() {
        fmt.Println(MapList(MapList(NewList(0, 2, 4), add(2)), divideBy(2))) // [1 2 3]
    }
    

    Because Go 1.18 didn’t support generic methods, we needed a generic function as a workaround. This is now remedied in Go 1.27:

    // after Go 1.27
    func (List[E]) Map[R any](f func(E) R) List[R] { /* ... */ }
    

    This is compact, expressive, and locally scoped. Additionally, chained calls are more readable, as they can be written more naturally from left to right:

    func main() {
        fmt.Println(NewList(0, 2, 4).Map(add(2)).Map(divideBy(2))) // [1 2 3]
    }
    

    Prefer the “inside out” form? A method expression can convert any method, including a generic one, into its function equivalent. Thus, a function call structure can be recovered if desired:

    func main() {
        f := List[int].Map[int]
        fmt.Println(f(f(NewList(0, 2, 4), add(2)), divideBy(2))) // [1 2 3]
    }
    

    Generic methods, like other generics in Go, must be instantiated (either explicitly or implicitly) before they are used (called or converted to a function).

    Decoupling things

    If one views methods also as an organizational tool, then Go 1.18’s reasoning appears overly restrictive. While a generic concrete method can’t help implement an interface (without generic interface methods), it can still be useful for code organization. In other words, these concerns can be decoupled.

    To elaborate, let’s consider a simple interface:

    type I interface {
        M()
    }
    type T struct{}                   // a struct, not an interface
    func (T) M[P any]() { /* ... */ } // a generic *concrete* method
    

    Here, T.M is parameterized by P. Any instantiation of T.M would result in a method signature identical to that of I.M:

    func main() {
        T{}.M[int]()
    }
    

    Both T.M[int] and I.M have the signature func M().

    However, this doesn’t mean T implements I. Interface implementation is a property of a (possibly instantiated) type, not of any particular method. Importantly, T does not declare T.M[int], but rather its generic (and thus uninstantiated) counterpart T.M.

    For T.M to participate in interface implementation, there would need to exist a suitable generic method I.M:

    type I interface {
        M[P any]() // a generic *interface* method
    }
    type T struct{}
    func (T) M[P any]() { /* ... */ }
    

    Since the Go 1.27 syntax doesn’t allow interface methods to declare type parameters, this code is impossible to write.

    But why can’t Go have generic interface methods? To understand, a bit of a detour is needed.

    The trouble with generic interface methods

    An interface value is a box that can hold some other value—the boxed value can be of any type, as long as that type implements the interface. This means that the declared methods on the type are a superset of those declared on the interface.

    To illustrate, T implements I below:

    type I interface {
        M()
    }
    type T struct{}
    func (T) M() { /* ... */ }
    

    One can call methods on interface values:

    func main() {
        F(T{})
    }
    
    func F(i I) {
        i.M() // "backed" by T.M
    }
    

    Above, it’s easy to observe that the call to i.M will be routed to T.M. But in more complex programs, the relation between an interface value method call and its possible targets is significantly less obvious. This relation typically spans across packages, making it difficult or impossible to deduce in the general case.

    To illustrate, let’s introduce a package boundary:

    // -- package main --
    import "p"
    
    func main() {
        p.F(T{})
    }
    type T struct{}
    func (T) M() { /* ... */ }
    
    // -- package p --
    func F(i I) {
        i.M()
    }
    type I interface {
        M()
    }
    

    Because the two packages are compiled separately, the main package won’t know how p.F uses T{}. To ensure the existence of any method that might call, the compiler generates code for all non-generic methods of a type at its declaration (or instantiation). That way, regardless of what p.F does with T{}, the necessary code will exist at runtime.

    Now, suppose that I.M were generic:

    // -- package main --
    import "p"
    
    func main() {
        p.F(T{})
    }
    type T struct{}
    func (T) M[P any]() { /* ... */ }
    
    // -- package p --
    func F(i I) {
        i.M[int]()
    }
    type I interface {
        M[P any]()
    }
    

    Again, the main package won’t know how p.F uses T{}—including how it might instantiate T.M. To handle any usage of T{} inside p.F, the compiler would need to instantiate T.M with every possible type argument.

    This is impractical with Go’s approach to instantiation, wherein the compiler generates specific code for each method based on the type arguments. If method arguments were “boxed” (i.e. passed as values of their constraint interfaces), each instantiation would share the same code. This would avoid having too many instantiations at the cost of indirect call overhead—even for direct calls to instantiated methods.

    Conclusion

    Go 1.27 introduces type parameters on concrete methods—this feature has been highly desired by the Go community, as it permits more ergonomic and readable code. Although we can’t support generic interface methods, we decided that allowing type parameters for concrete methods was still worthwhile.

    We hope you enjoy using Go’s generic methods and find helpful ways to use them in your projects!

    Original source
  • Aug 19, 2026
    • Date parsed from source:
      Aug 19, 2026
    • First seen by Releasebot:
      Aug 20, 2026
    Google logo

    Go by Google

    Go 1.27 is released

    Go 1.27 releases major updates across the language, toolchain, runtime, and standard library, including generic methods, smarter type inference, new go fix modernizers, faster allocation performance, and additions like encoding/json/v2, crypto/mldsa, and native UUID support.

    Today the Go team is pleased to release Go 1.27. You can find its binary archives and installers on the download page.

    Go 1.27 brings major enhancements across the language, toolchain, runtime, and standard library. Below are some of the key highlights.

    Language changes

    Go 1.27 introduces three notable updates to the language specification.

    First, generic methods are now supported. For example, see math/rand/v2.Rand:

    // Prior to Go 1.27, a separate method on Rand had to be added for each type
    // (unsigned integer methods omitted for brevity).
    func (r *Rand) Int32N(n int32) int32
    func (r *Rand) Int64N(n int64) int64
    func (r *Rand) IntN(n int)
    
    // Go 1.27 adds a new generic method that works for all integer types.
    func (r *Rand) N[Int intType](n Int) Int
    

    Second, a key in a struct literal may now be any valid field selector for the struct type, allowing fields in nested or embedded structs to be initialized directly:

    type Habitat struct {
        Burrow string
    }
    
    type Gopher struct {
        Name    string
        Habitat // Embedded struct.
    }
    
    // Go 1.27 allows using Burrow as a key directly.
    g := Gopher{
        Name:   "Gopher",
        Burrow: "Burrow #42",
    }
    

    Finally, function type inference has been generalized to apply in all assignment contexts. Generic functions can now be used without explicit type arguments in composite literals, type conversions, and channel sends:

    func GenericFormatter[T any](v T) string {
        return fmt.Sprintf("value: %v", v)
    }
    
    type IntFormatter func(int) string
    
    // Go 1.27 infers T = int in composite literals, conversions, and channel sends.
    formatters := []IntFormatter{GenericFormatter}
    fn := IntFormatter(GenericFormatter)
    ch := make(chan IntFormatter, 1)
    ch <- GenericFormatter
    

    Tool improvements

    • go fix includes several new modernizers: atomictypes, embedlit, slicesbackward, and unsafefuncs.
    • go doc now supports package@version queries such as go doc example.com/[email protected].
    • go mod tidy now automatically consolidates multiple require blocks in go.mod into a standard direct and indirect two-block structure.

    Performance and runtime

    • Size-specialized memory allocation reduces small object (<80B) allocation costs by up to 30%, improving overall performance by ~1% for allocation-heavy programs.
    • The goroutineleak profile in runtime/pprof is now generally available, allowing automatic detection of permanently blocked goroutines.

    Standard library additions

    • encoding/json/v2 provides high-level JSON processing with configurable options and stricter defaults, alongside encoding/json/jsontext for low-level streaming. The existing encoding/json package is now backed by the v2 implementation for faster unmarshaling while maintaining backwards compatibility.
    • crypto/mldsa implements the post-quantum ML-DSA signature scheme (FIPS 204), integrated into crypto/x509 and crypto/tls.
    • uuid provides native support for generating and parsing UUIDs.
    • simd and architecture-specific simd/archsimd provide experimental SIMD support.
    • net/http/httptest adds NewTestServer, providing an in-memory fake network suitable for use with the testing/synctest package.

    Please read the Go 1.27 release notes for the complete list of changes and details.

    Over the next few weeks, follow-up blog posts will cover some of the topics relevant to Go 1.27 in more detail. Check back later to read those posts.

    Thanks to everyone who contributed to this release by writing code, filing bugs, trying out experimental additions, and testing release candidates. As always, if you notice any problems, please file an issue.

    We hope you enjoy using Go 1.27!

    Original source
  • Aug 19, 2026
    • Date parsed from source:
      Aug 19, 2026
    • First seen by Releasebot:
      Aug 19, 2026
    Google logo

    Go by Google

    Go 1.26.7 and Go 1.25.14 are released

    Go releases minor point updates for Go 1.26.7 and Go 1.25.14, fixing a breakage in unencrypted HTTP/2 h2c connections caused by a recent security patch. The fix is also included in Go 1.27.0.

    Hello gophers,

    We have just released Go versions 1.26.7 and 1.25.14, minor point releases.

    View the release notes for more information:

    https://go.dev/doc/devel/release#go1.26.7

    You can download binary and source distributions from the Go website:

    https://go.dev/dl/

    To compile from source using a Git clone, update to the release with

    git checkout go1.26.7
    

    and build as usual.

    Thanks to everyone who contributed to the releases.

    Cheers,

    Carlos and Dmitri for the Go team

    Hello gophers,

    These minor releases include a fix to address a breakage affecting unencrypted HTTP/2 (h2c) connections caused by a security patch included in last week’s release. See

    go.dev/issue/80876

    for details. This fix is also included in Go 1.27.0 (also being released today).

    Thanks,

    Carlos and Dmitri for the Go team

    Original source
  • August 2026
    • No date parsed from source.
    • First seen by Releasebot:
      Aug 19, 2026
    Google logo

    Go by Google

    Go 1.27.0 is released

    Go releases 1.27.0 with new release notes, downloads, and source build instructions.

    Hello gophers,

    We have just released Go 1.27.0.

    To find out what has changed in Go 1.27, read the release notes:
    https://go.dev/doc/go1.27

    You can download binary and source distributions from our download page:
    https://go.dev/dl/#go1.27.0

    If you have Go installed already, an easy way to try go1.27.0
    is by using the go command:

    $ go install golang.org/dl/go1.27.0@latest
    $ go1.27.0 download
    

    To compile from source using a Git clone, update to the release with

    git checkout go1.27.0
    

    and build as usual.

    Thanks to everyone who contributed to the release!

    Cheers,
    Carlos and Dmitri for the Go team

    Original source
  • Aug 13, 2026
    • Date parsed from source:
      Aug 13, 2026
    • First seen by Releasebot:
      Aug 14, 2026
    Google logo

    Go by Google

    [security] Vulnerabilities in golang.org/x/mod

    Go releases golang.org/x/mod v0.40.0 with security fixes for sumdb transparency log verification and Lookup handling, closing vulnerabilities that could let malicious module content bypass integrity checks and persist in the local cache.

    Hello gophers,

    We have tagged version v0.40.0 of golang.org/x/mod in order to address the following security issues:

    x/mod/sumdb/tlog: fix transparency log tile verification bypass

    A malicious GOPROXY was previously capable of forging up to two sumdb tiles that allow for a requested module to bypass the GOSUMDB check and persist attacker-controlled module content to a local Go module cache.

    This attack allows for a malicious GOPROXY to serve malicious module content that cannot be detected by evaluating the transparency log.

    All tiles are now correctly verified against their parents.

    In order to determine if you have been affected:

    rm -r go.sum go.work.sum vendor/ && go mod tidy
    

    Thanks to Filippo Valsorda (Geomys) for reporting this issue.

    This is CVE-2026-56865 and Go issue https://go.dev/issue/80744.

    x/mod/sumdb: ignore unrelated, unauthenticated hashes in Lookup

    A malicious GOSUMDB was capable of serving arbitrary module content not contained within the transparency log.

    This attack allows for a coordinating GOPROXY and GOSUMDB to serve a client malicious module content that cannot be detected by evaluating the transparency log.

    In order to determine if you have been affected:

    rm -r go.sum go.work.sum vendor/ && go mod tidy
    

    Thanks to mundur for reporting this issue.

    This is CVE-2026-56864 and Go issue https://go.dev/issue/80745.

    Cheers,
    Go Security team

    Original source
Releasebot

Curated by the Releasebot team

Releasebot is an aggregator of official product update announcements from hundreds of software vendors and thousands of sources.

Our editorial process involves the manual review and audit of release notes procured with the help of automated systems.