Go语言中的惯用类型转换

10
我在尝试使用Go语言编程,并想知道在Go中进行语言风格的类型转换的最佳方法。我的问题基本上在于uint8uint64float64之间的自动类型转换。从我在其他语言的经验来看,将uint8uint64相乘将产生一个uint64值,但在Go中并非如此。
以下是我构建的一个示例,我想知道这是否是编写此代码的语言风格或者我是否遗漏了某个重要的语言结构。
package main

import ("math";"fmt")

const(Width=64)

func main() {

    var index uint32
    var bits uint8

    index = 100
    bits = 3

    var c uint64
    // This is the line of interest vvvv
    c = uint64(math.Ceil(float64(index * uint32(bits))/float64(Width)))
    fmt.Println("Test: %v\n", c)
}

我认为计算天花板值因为所有显式类型转换而变得不必要的复杂。

谢谢!


为什么要使用浮点数运算?http://play.golang.org/p/kdV9vnIqPN - zzzz
假设您有两个存储8位整数的64位宽块,并且您想要存储9个元素,需要知道分配多少块才能消除开销。9 * 8/64 = 1,但是8 * 8/64 = 1也是如此。也许我错过了一个有趣的+/-1的东西...... - grundprinzip
2
使用:(98+(64-1))/64 = 2 和 (88+(64-1))/64 = 1。请查看我的答案。 - peterSO
将uint8/byte设置为float64,使用float64(b[0])。请参见https://dev59.com/CmIk5IYBdhLWcg3wfOSe#62725637。 将float64设置为uint8/byte,使用byte(f)。请参见https://dev59.com/XlsW5IYBdhLWcg3wT155#62753031。 - user12817546
3个回答

7

对于非常量值,没有隐式类型转换。

您可以编写

var x float64
x = 1

但是你不能写

var x float64
var y int

y = 1
x = y

请参考规范

不允许自动/隐式类型转换有很好的理由,因为它们可能变得非常混乱,而且人们必须学习许多规则来规避可能发生的各种注意事项。例如,看看C语言中的整数转换规则


1
例如,
package main

import "fmt"

func CeilUint(a, b uint64) uint64 {
    return (a + (b - 1)) / b
}

func main() {
    const Width = 64
    var index uint32 = 100
    var bits uint8 = 3
    var c uint64 = CeilUint(uint64(index)*uint64(bits), Width)
    fmt.Println("Test:", c)
}

输出:

Test: 5

尽管它本身是正确的,但另一个答案才是我正在寻找的。谢谢。 - grundprinzip

1
为了补充@ nemo出色的回答。在C语言中数字类型之间的自动转换方便性被混淆引起的困惑所抵消。请参见https://Golang.org/doc/faq#conversions。这就是为什么您甚至不能隐式地将int转换为int32。请参见https://dev59.com/aGYr5IYBdhLWcg3wOXwQ#13852456
package main

import (
    . "fmt"
    . "strconv"
)

func main() {
    i := 71
    c := []interface{}{byte(i), []byte(string(i)), float64(i), i, rune(i), Itoa(i), i != 0}
    checkType(c)
}

func checkType(s []interface{}) {
    for k, _ := range s {
        Printf("%T %v\n", s[k], s[k])
    }
}

byte(i) 生成一个值为71的 uint8,[]byte(string(i)) 生成一个包含[71]的 []uint8,float64(i) 生成一个值为71.0的 float64,i 生成一个值为71的 int,rune(i) 生成一个值为71的 int32,Itoa(i) 将整数i转换成字符串"71",i != 0 生成一个值为true的 bool。

由于Go不会自动为您转换数值类型(请参阅 https://dev59.com/aGYr5IYBdhLWcg3wOXwQ#13851553),因此您必须手动在类型之间进行转换。请参阅 https://dev59.com/aGYr5IYBdhLWcg3wOXwQ#41419962。注意,Itoa(i)将“整数转换为ASCII”。请参阅https://dev59.com/3mkw5IYBdhLWcg3wJXIh#10105983中的注释。


布尔型、数值型或字符串型可以设置为另一种类型。有关[]byte的信息,请参见https://dev59.com/CmIk5IYBdhLWcg3wfOSe#62725637;有关`float64`的信息,请参见https://dev59.com/XlsW5IYBdhLWcg3wT155#62753031;有关`int`的信息,请参见https://dev59.com/e2Yr5IYBdhLWcg3w0taE#62737936;有关`string`的信息,请参见https://dev59.com/OVwZ5IYBdhLWcg3waPvX#62740786;有关`bool`的信息,请参见https://dev59.com/Y2oy5IYBdhLWcg3wq_7O#62726854。 - user12817546

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接