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

Radar · Go · #001 · Week 39 · Sep 21 – 27, 2026

spec: remove string(int)

Worth knowinglanguage

What changed
Accepted: from language version 1.28, an integer can be converted to a string only if its type is byte or rune, or if it is an untyped rune constant such as 'A'. This lifts a check that go vet has made for years into the language itself.
Production impact
Code that converts other integer types with string(i) stops compiling once its module's go.mod says go 1.28 or later; go vet already reports these conversions today.
Try it
Run go vet ./... on your module: it reports each string(i) the new rule will reject.
Source
github.com/golang/go/issues/3939

Understand it, then run it

Converting an integer to a string with string(i) does not give you its digits. It gives you the character whose Unicode code point is i: string(65) is "A", not "65". This surprises almost everyone who meets it, which is why go vet has warned about it for years.

The accepted proposal makes the rule part of the language. From language version 1.28, string(i) compiles only when i is a byte or a rune, the two integer types that already mean "a character". If you want the digits, use strconv.Itoa(i).

Run it now

Todaygo
package main

import (
	"fmt"
	"strconv"
)

// Compiles on Go 1.27.1. string(i) with an int is the form the new rule
// removes from language version 1.28: it gives the character whose Unicode
// code point is i, never the digits of i.
func main() {
	for _, i := range []int{65, 0x1F600, -1} {
		fmt.Printf("i = %d\n", i)
		fmt.Printf("  string(i)        = %q\n", string(i))       // the form Go 1.28 removes
		fmt.Printf("  string(rune(i))  = %q\n", string(rune(i))) // the same character, said explicitly
		fmt.Printf("  strconv.Itoa(i)  = %q\n", strconv.Itoa(i)) // the digits, if that was meant
	}
}

What it printed when we ran it on Go 1.27.1

i = 65
  string(i)        = "A"
  string(rune(i))  = "A"
  strconv.Itoa(i)  = "65"
i = 128512
  string(i)        = "😀"
  string(rune(i))  = "😀"
  strconv.Itoa(i)  = "128512"
i = -1
  string(i)        = "�"
  string(rune(i))  = "�"
  strconv.Itoa(i)  = "-1"

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.

Written by gpt-oss-120b from the linked source · claims checked against the sources · human-reviewed