英文:
Idiomatic Type Conversion in Go
问题
我在使用Go语言时遇到了一些问题,想知道在Go中执行惯用类型转换的最佳方法是什么。基本上,我的问题在于uint8
、uint64
和float64
之间的自动类型转换。根据我在其他语言的经验,uint8
与uint64
的乘法将产生一个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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论