-3

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"))
riad
  • 23
  • 1
  • 5
  • 3
    As @Hymns has noted the `int` to `string` conversion is a raw conversion - and probably not the one you expect. If you want a `string` representation of a particular `int` - use `strconv.Itoa(x)` or `fmt.Sprint(x)` – colm.anseo Apr 26 '21 at 20:28
  • 6
    For the record, there is an [active proposal](https://github.com/golang/go/issues/3939) to disallow this due to potentially odd/confusing behavior of this conversion – blackgreen Apr 26 '21 at 20:39

3 Answers3

1

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.

Hymns For Disco
  • 7,530
  • 2
  • 17
  • 33
  • Thanks for your explanation. I experimented with that. I was using it in a function where I only convert if the values are convertible like float to int, int to float, etc. Converting an int to a string was counterintuitive to me, int to rune is okay, though rune is an alias to int32. If I want to string from int or int from string there are functions from `strconv` package. Anyway, it's a language decision I think. – riad Apr 26 '21 at 20:43
  • The conversion functions in `strconv` are not the same as what you get with `string(someint)`. – Adrian Apr 26 '21 at 21:19
1

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"

blackgreen
  • 34,072
  • 23
  • 111
  • 129
Volker
  • 40,468
  • 7
  • 81
  • 87
0

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)))
EvgenyKolyakov
  • 3,310
  • 2
  • 21
  • 31