This site is being rebuilt and some pages are out of date. For current details, write to [email protected]. This notice goes away when the rebuild is done.

No analytics unless you allow it, no tracking. This site keeps in your browser the language you pick, the theme, its colour, which site you chose, the currency on the pricing page and that you closed this notice; signing in adds session cookies. The legal page has the details.

Sign in

Quiet Pager · Radar

What changed in Go, Rust and Solidity this week.

What changed this week, from each project's own release notes, proposals and issues, with an exercise you can run for each change.

Written by a model · reviewed by a person · published Mondays · Atom feed

Archive · Week 8 · Feb 17 – 23, 2025from 3 items

This week the Go team focused on refining the language’s type system and tooling, and introduced an experimental package for testing concurrent code. The changes are mostly incremental, but they touch on core concepts that may affect long‑term maintenance and tooling pipelines.

Worth knowinglanguage

Remove notion of core types

What changed
The proposal removes the notion of “core types” from the language specification, replacing the investigative issue with a concrete proposal.
Production impact
The source does not say.
Try it
Read the proposal text in the issue to see how type constraints are now described.
Source
github.com/golang/go/issues/70128
Explain it and run it

Understand it, then run it

Run it now

Todaygo
// This program demonstrates the current limitation that a slice expression
// cannot be applied directly to a type parameter. After the proposed change,
// the slice expression would be allowed for generic operands with a suitable
// type set. Until that change ships, we must use a type switch or assertion
// to slice the underlying concrete type.

package main

import (
	"fmt"
)

// Constraint allows either a slice of int or a string.
type Constraint interface {
	~[]int | ~string
}

// sliceGeneric attempts to slice a value of type T.
// Because T is a type parameter, a direct slice expression like v[i:j]
// is not permitted in Go 1.27.1. We work around this by using a type switch.
func sliceGeneric[T Constraint](v T, i, j int) interface{} {
	switch x := any(v).(type) {
	case []int:
		return x[i:j]
	case string:
		return x[i:j]
	default:
		return nil
	}
}

func main() {
	// Example with a slice of int.
	intSlice := []int{10, 20, 30, 40, 50}
	fmt.Println("Slicing []int:", sliceGeneric(intSlice, 1, 4))

	// Example with a string.
	str := "hello world"
	fmt.Println("Slicing string:", sliceGeneric(str, 6, 11))
}

What it printed when we ran it on Go 1.27.1

Slicing []int: [20 30 40]
Slicing string: world

Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.

Worth knowingtooling

Testing concurrent code with testing/synctest

What changed
Go 1.24 contains an experimental package, testing/synctest, to aid in testing concurrent code.
Production impact
The source does not say.
Try it
Add testing/synctest to a test file and experiment with its helpers to see how it can simplify concurrent tests.
Source
go.dev/blog/synctest
Explain it and run it

Understand it, then run it

Go 1.24 adds an experimental package called testing/synctest. It gives helpers for writing tests that involve goroutines and channels. Instead of waiting a fixed time to see if something happens, you can wrap the test in synctest.Run and call synctest.Wait. Wait blocks until all goroutines started inside the test are blocked on each other, so you know whether a function will run or not. This makes concurrent tests faster and less flaky.

Run it now

Todaygo
// This program demonstrates the experimental testing/synctest package
// which is available in Go 1.24 and later.  It is not part of the
// standard library in Go 1.27.1, so the code will not compile
// unless the GOEXPERIMENT=synctest flag is set and the package
// is available.  The program prints the result of a simple
// concurrent test using synctest.Run and synctest.Wait.

package main

import (
	"context"
	"fmt"
	"time"

	// The experimental package is not part of the standard library
	// in Go 1.27.1.  It is available when GOEXPERIMENT=synctest.
	// Uncomment the import below when the experiment is enabled.
	// "testing/synctest"
)

func main() {
	// Since synctest is experimental, we cannot import it here
	// in a standard Go 1.27.1 environment.  The following code
	// shows how it would be used once the package is available.
	//
	// synctest.Run(func() {
	//     ctx, cancel := context.WithCancel(context.Background())
	//
	//     called := false
	//     context.AfterFunc(ctx, func() { called = true })
	//
	//     synctest.Wait()
	//     if called {
	//         fmt.Println("AfterFunc called before cancel")
	//     } else {
	//         fmt.Println("AfterFunc not called yet, as expected")
	//     }
	//
	//     cancel()
	//
	//     synctest.Wait()
	//     if called {
	//         fmt.Println("AfterFunc called after cancel, as expected")
	//     } else {
	//         fmt.Println("AfterFunc did not run after cancel")
	//     }
	// })

	// Instead, we simulate the same logic with a simple channel
	// to illustrate the intended behavior.
	ctx, cancel := context.WithCancel(context.Background())
	calledCh := make(chan struct{})
	go func() {
		<-ctx.Done()
		close(calledCh)
	}()

	// Wait briefly to ensure the goroutine hasn't run yet.
	time.Sleep(10 * time.Millisecond)
	select {
	case <-calledCh:
		fmt.Println("Unexpected: goroutine ran early")
	default:
		fmt.Println("Goroutine has not run yet, as expected")
	}

	cancel()

	// Wait for the goroutine to finish.
	<-calledCh
	fmt.Println("Goroutine ran after cancel, as expected")
}

What it printed when we ran it on Go 1.27.1

Goroutine has not run yet, as expected
Goroutine ran after cancel, as expected

After the change ships

go · the proposal's code; it does not compile until the change ships

// This code does not compile until the testing/synctest package
// is available in the Go release (GOEXPERIMENT=synctest).

package main

import (
	"context"
	"fmt"
	"testing/synctest"
)

func main() {
	synctest.Run(func() {
		ctx, cancel := context.WithCancel(context.Background())

		called := false
		context.AfterFunc(ctx, func() { called = true })

		synctest.Wait()
		if called {
			fmt.Println("AfterFunc called before cancel")
		} else {
			fmt.Println("AfterFunc not called yet, as expected")
		}

		cancel()

		synctest.Wait()
		if called {
			fmt.Println("AfterFunc called after cancel, as expected")
		} else {
			fmt.Println("AfterFunc did not run after cancel")
		}
	})
}

Run sends this program (for Solidity, the contract and its tests) to our own sandbox, where it is compiled and run once, with no network, and what it printed or the test report comes back here. Nothing is kept. Runs are counted per visitor for the day so everyone gets a turn; the details are on the legal page.

Nice to knowtooling

Deprecate parser.ParseDir

What changed
The Go team marked parser.ParseDir as deprecated. It will still exist and be usable, but it returns ast.Package, which is already deprecated.
Production impact
The source does not say.
Try it
Run go vet on a project that uses parser.ParseDir to see the deprecation warning.
Source
github.com/golang/go/issues/71122
Explain it

Understand it, then run it

The parser.ParseDir function is a helper that walks a directory and turns every Go file it finds into an abstract syntax tree (AST). The Go team has marked this helper as *deprecated*. That means it still works, but the type it returns, ast.Package, is also deprecated. When you use parser.ParseDir in a new project, your IDE will warn you that the function is old and that you should look for a newer alternative.

The warning does not break your code; it just tells you that the library may remove the function in a future release. The change is part of the normal evolution of the standard library, where older APIs are phased out gradually.

If you are writing a small script or a learning example, you can keep using parser.ParseDir. Just be aware that in the future you might need to switch to a different approach, such as walking the directory yourself and calling parser.ParseFile on each file.

Exercise

Write a small program that parses a Go source file into an AST, then prints the names of all top‑level functions found in the file.

The 60-second version

This week the Go team refined how the language handles type constraints, removing an old concept called “core types” to simplify the specification. They also marked an older parsing helper as deprecated, nudging developers toward newer APIs that avoid deprecated AST types. Finally, a new experimental package, testing/synctest, was added to help write tests for concurrent code more easily. These updates are incremental but point toward a cleaner, more future‑proof language and tooling ecosystem.

Written by gpt-oss-20b · claims checked against the sources · archive, not individually reviewed