Go中的惯用类型转换

huangapple go评论80阅读模式
英文:

Idiomatic Type Conversion in Go

问题

我在使用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
    // 这是我关注的那一行 vvvv
    c = uint64(math.Ceil(float64(index * uint32(bits))/float64(Width)))
    fmt.Println("Test: %v\n", c)
}

在我看来,计算天花板值似乎过于复杂,因为涉及了许多显式类型转换。

谢谢!

英文:

I was playing around with Go and was wondering what the best way is to perform idiomatic type conversions in Go. Basically my problem lays within automatic type conversions between uint8, uint64, and float64. From my experience with other languages a multiplication of a uint8 with a uint64 will yield a uint64 value, but not so in go.

Here is an example that I build and I ask if this is the idiomatic way of writing this code or if I'm missing an important language construct.

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)
}

From my point of view the calculation of the ceiling value seems unnecessary complex because of all the explicit type conversions.

Thanks!

答案1

得分: 7

非常抱歉,我只能提供英文翻译。以下是您要翻译的内容:

There are no implicit type conversions for non-constant values.

You can write

var x float64
x = 1

But you cannot write

var x float64
var y int

y = 1
x = y

See the spec for reference.

There's a good reason, to not allow automatic/implicit type conversions, as they can
become very messy and one has to learn many rules to circumvent the various caveats
that may occur. Take the Integer Conversion Rules in C for example.

英文:

There are no implicit type conversions for non-constant values.

You can write

var x float64
x = 1

But you cannot write

var x float64
var y int

y = 1
x = y

See the spec for reference.

There's a good reason, to not allow automatic/implicit type conversions, as they can
become very messy and one has to learn many rules to circumvent the various caveats
that may occur. Take the Integer Conversion Rules in C for example.

答案2

得分: 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
英文:

For example,

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)
}

Output:

Test: 5

答案3

得分: 1

为了补充@nemo出色的回答。在C语言中,自动转换数值类型的便利性被造成的混淆所抵消。请参见https://Golang.org/doc/faq#conversions。这就是为什么你甚至不能隐式地从int转换为int32。请参见https://stackoverflow.com/a/13852456/12817546。

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的float64,i创建一个值为71的int,rune(i)创建一个值为71的int32,Itoa(i)创建一个值为"71"的string,i != 0创建一个值为true的bool。

由于Go不会自动为您转换数值类型(请参见https://stackoverflow.com/a/13851553/12817546),您必须手动在类型之间进行转换。请参见https://stackoverflow.com/a/41419962/12817546。请注意,Itoa(i)将一个"整数转换为ASCII"。请参见https://stackoverflow.com/a/10105983/12817546中的注释。

英文:

To add to @nemo terrific answer. The convenience of automatic conversion between numeric types in C is outweighed by the confusion it causes. See https://Golang.org/doc/faq#conversions. Thats why you can't even convert from int to int32 implicitly. See https://stackoverflow.com/a/13852456/12817546.

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) creates a uint8 with a value of 71, []byte(string(i)) a []uint8 with [71], float64(i) float64 71, i int 71, rune(i) int32 71, Itoa(i) string 71 and i != 0 a bool with a value of true.

Since Go won't convert numeric types automatically for you (See https://stackoverflow.com/a/13851553/12817546) you have to convert between types manually. See https://stackoverflow.com/a/41419962/12817546. Note, Itoa(i) sets an "Integer to an ASCII". See comment in https://stackoverflow.com/a/10105983/12817546.

huangapple
  • 本文由 发表于 2012年11月14日 04:10:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/13367979.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定