Why is "int" convertible to "string"?

1.3k Views Asked by At

This example shows that int type is convertible to string type. But my question is why?

package main

import (
    "fmt"
    "reflect"
)

func main() {
    it := reflect.TypeOf(42)
    st := reflect.TypeOf("hello")

    fmt.Printf("%q is convertible to %q: %v\n",
        it, st, it.ConvertibleTo(st))
        // OUTPUT: "int" is convertible to "string": true

    fmt.Printf("%q is convertible to %q: %v\n",
        st, it, st.ConvertibleTo(it))
        // OUTPUT: "string" is convertible to "int": false
}

Correct me if I'm wrong. But Shouldn't this be false as well?

reflect.TypeOf(int(0)).ConvertibleTo(reflect.TypeOf("string"))
3

There are 3 best solutions below

0
On BEST ANSWER

Why is “int” convertible to “string”?

Because the language spec1 says so:

Converting a signed or unsigned integer value to a string type yields a string containing the UTF-8 representation of the integer.

1: Conversions, section "Conversions to and from a string type"

2
On

The meaning of int to string conversion is to create a string with one unicode character: the character that is identified by that int's number.

See this example:

package main

import (
    "fmt"
)

func main() {
    fmt.Println(string(int(1234)))
}

On playground

Output:

Ӓ

This is because Unicode character 1234 (or U+04D2 in the more standard representation) is:

CYRILLIC CAPITAL LETTER A WITH DIAERESIS


You will also notice that on the Go playground, you'll see a red output from go vet, which is a tool to find common problems in Go programs. The output warns:

./prog.go:8:14: conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)

This is because this kind of conversion is rather strange and not commonly used, so go vet basically sees it as a potential mistake by default.

0
On

The fmt.Println() & fmt.Sprintf() treat arguments differently.

You can feed fmt.Println() anything and it'll print it('s %v) - like:

fmt.Println(string(97)) // a

fmt.Sprintf() will work, but give you a warning about conversion from int to string yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?) if you try something like:

x := fmt.Sprintf("%s", string(97))

Because string() treats integers the "Go" way.

So to print a rune correctly (like the chr() function in most other languages), one should cast the int to rune first, like so:

x := fmt.Sprintf("%s", string(rune(97)))