【极客日常】Go语言string、int、float、rune、byte等数据类型的转换方法

golang的数据类型转换是困惑新gopher的一大问题之一。相对于python,golang的数据类型转换可要麻烦的多,而且还不走寻常路地诞生了些新的方法跟名词。因此本文讲解golang常见数据类型string、int、rune等数据类型相互之间的转换方法,给大伙儿避坑。

在讲述方法之前,首先非常有必要讲下go源码对这些数据类型的表述:

// string is the set of all strings of 8-bit bytes, conventionally but not
// necessarily representing UTF-8-encoded text. A string may be empty, but
// not nil. Values of string type are immutable.
type string string

// int is a signed integer type that is at least 32 bits in size. It is a
// distinct type, however, and not an alias for, say, int32.
type int int

// int32 is the set of all signed 32-bit integers.
// Range: -2147483648 through 2147483647.
type int32 int32

// uint64 is the set of all unsigned 64-bit integers.
// Range: 0 through 18446744073709551615.
type uint64 uint64

// float32 is the set of all IEEE-754 32-bit floating-point numbers.
type float32 float32

// float64 is the set of all IEEE-754 64-bit floating-point numbers.
type float64 float64

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32

从上面的描述我们可以获得以下信息:

  • int有符号,至少32位,但并不是int32的别称。如果把大于2147483647的数赋值intint打出来也是正常的,没有损失精度
  • rune就是int32,实际一般用来表示字符char的值。和一般的char不一样的是rune的精度比较高= =,并且golang也没有char这个内置关键字
  • byte就是uint8,实际一般用来表示二进制数据中比特的值

因此对于runebyte这边,就可以当作uint8跟int32相关的转换了,这块的理解就容易得多

首先看字符串stringintfloat等数值的转换:

func testStringToDigit() {
    fmt.Println("=============== test string to digit ==================")

    var s string = "1234567"
    var i int
    var i32 int32
    var ui64 uint64

    i, _ = strconv.Atoi(s)
    i64, _ := strconv.ParseInt(s, 10, 32)
    i32 = int32(i64)
    ui64, _ = strconv.ParseUint(s, 10, 64)
    fmt.Printf("string: %s, int: %d, int32:%d, uint64: %d\n",
        s, i, i32, ui64)

    var sf string = "1234512345.12345678901234"
    var f32 float32
    var f64 float64

    f64, _ = strconv.ParseFloat(sf, 64)
    f32In64, _ := strconv.ParseFloat(sf, 32)
    f32 = float32(f32In64)
    fmt.Printf("string: %s, float32: %f, float64: %f\n",
        sf, f32, f64)

    fmt.Println("====================================================")
}

stringintstrconv.Atoi方法,而对于其它有bitSize限制的数据,则用strconv.ParseInt或者strconv.ParseFloat先转换成64位再调精度即可。

然后看数值到string的转换:

func testDigitToString() {
    fmt.Println("=============== test digit to string ==================")

    var i int = 12345
    var i32 int32 = -678
    var ui64 uint64 = 901234567890
    var strInt string = fmt.Sprintf("%d", i)
    var strInt32 string = strconv.FormatInt(int64(i32), 10)
    var	strUInt64 string = strconv.FormatUint(ui64, 10)
    fmt.Printf("strInt: %s, strInt32: %s, strUInt64: %s\n",
        strInt, strInt32, strUInt64)

    var f32 float32 = 3.1415926
    var f64 float64 = -3.1415926535897
    var strFloat32 string = fmt.Sprintf("%.5f", f32)
    var strFloat64 string = strconv.FormatFloat(f64, 'f', 10, 64)
    fmt.Printf("strFloat32: %s, strFloat64: %s\n", strFloat32, strFloat64)

    fmt.Println("====================================================")
}

数值到string,最简单粗暴的方法是fmt.Sprintf格式化字符串。如果需要精调,则得用strconv.ParseIntstrconv.ParseFloat等方式。值得一提的是strconv.ParseFloat注释了多种格式可供选择,有兴趣的同学可以看源码。

stringrunebyte之类数据的转换,可以如下:

func testStringAndRuneAndByte() {
    fmt.Println("=============== test string & rune & byte ==================")

    var s string = "helloworld"
    var runes []rune = []rune(s)
    var bytes []byte = []byte(s)
    fmt.Printf("string: %s, runes: %v, bytes: %v\n", s, runes, bytes)

    for i, char := range s {
        if i >= 0 {
            fmt.Printf("type of index: %T\n", i) // int
            fmt.Printf("type of char: %T\n", char)  // int32
            fmt.Printf("digit value of char: %d\n", char) // 104
            fmt.Printf("output char: %c\n", char) // h
            fmt.Printf("is equal with rune value: %v\n", 'h' == rune(char)) // true
            fmt.Printf("is equal with byte value: %v\n", 'h' == byte(char)) // true
            // invalid expression -> rune: int32, byte: uint8
            // fmt.Printf("is rune & byte equals: %v\n", rune(char) == byte(char))
            break
        }
    }

    fmt.Println("====================================================")
}

[]rune[]byte可直接将string变为charArray。值得一提的是,遍历string时每个char字符的类型为int32,可用rune表示;字符表达式'h'可以直接和runebyte类型数字用==比较。

然后,由于runebyte本身就是int系,所以这两个和int系类型间的转换会非常简单

func testIntAndRuneAndByte() {
    fmt.Println("=============== test int & rune & byte ==================")

    var i int
    var r rune
    var b byte
    var ui8 uint8

    i, r = 123456, 123456
    fmt.Printf("int is equal with rune int: %v\n", int32(i) == r) // true
    b, ui8 = 'a', 'a'
    fmt.Printf("byte char is equal with uint8 char: %v\n", b == ui8) // true
    i = int('a')
    r, b, ui8 = rune(i), byte(i), uint8(i)
    fmt.Printf("int: %c, rune: %c, byte: %c, uint8: %c\n", i, r, b, ui8) // 4 * 'a'

    fmt.Println("====================================================")
}

最后一个tips是通用数据类型interface{}转特定数据格式的方法,可以这样操作:

func testInterfaceToInt() {
    fmt.Println("=============== test interface to digit ==================")

    var itf interface{}
    itf = 1234567890123456789
    i := itf.(int)

    // cannot convert to int32/int64/float32/float64

    fmt.Printf("interface: %v, int: %d\n", itf, i)

    fmt.Println("====================================================")
}

注意interface{}赋值了个int,如果直接带后缀.(int32)这样指定其它数据类型,会直接报错

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值