golang 的那些花样
2024-01-08 21:11:42
从 A Tour of Go 可以看到一些 Go 比较特殊的点
变量声明时,类型放在后面
var i, j int = 1, 2
Array 的引用 Slice
receiver 和 argument
receiver 习惯用于改变值,尤其是大的struct
type Vertex struct {
X, Y float64
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
argument 就是method的参数,习惯用于业务逻辑
type Vertex struct {
X, Y float64
}
func AbsFunc(v Vertex) float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
receiver 用于实现接口,用于业务逻辑
type Abser interface {
Abs() float64
}
func main() {
var a Abser
v := Vertex{3, 4}
a = &v // a *Vertex implements Abser
fmt.Println(a.Abs())
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
built-int特殊接口Error
package main
import (
"fmt"
"math"
)
type ErrNegativeSqrt float64
func (x ErrNegativeSqrt) Error() string {
return fmt.Sprintf("cannot Sqrt negative number: %f", x)
}
func Sqrt2(x float64) (float64, error) {
fmt.Println("processing.......")
if x>0 {
z := float64(1)
z = 0.5
fmt.Println(z)
for i:=0; math.Abs(z*z -x)>0.00001; i++ {
z = z - (z*z -x )/(2*z)
fmt.Println("i", i, "z", z, "z*z -x", z*z -x)
}
fmt.Println("finished.")
return z, nil
} else {
return 0, ErrNegativeSqrt(x)
}
}
func main() {
fmt.Println(Sqrt2(2))
fmt.Println(Sqrt2(-2))
}
这里面如果在实现Error接口的时候调fmt.Sprintf用了%v
,会再次调x.Error()
进行无限循环, 如果用%v
的话先把值转换出来float64(x)
func (x ErrNegativeSqrt) Error() string {
return fmt.Sprintf("cannot Sqrt negative number: %v", float64(x))
}
查看golang源码 https://cs.opensource.google/go/go/+/refs/tags/go1.17:src/fmt/print.go;l=617
// If we're doing Go syntax and the argument knows how to supply it, take care of it now.
if p.fmt.sharpV {
if stringer, ok := p.arg.(GoStringer); ok {
handled = true
defer p.catchPanic(p.arg, verb, "GoString")
// Print the result of GoString unadorned.
p.fmt.fmtS(stringer.GoString())
return
}
} else {
// If a string is acceptable according to the format, see if
// the value satisfies one of the string-valued interfaces.
// Println etc. set verb to %v, which is "stringable".
switch verb {
case 'v', 's', 'x', 'X', 'q':
// Is it an error or Stringer?
// The duplication in the bodies is necessary:
// setting handled and deferring catchPanic
// must happen before calling the method.
switch v := p.arg.(type) {
case error:
handled = true
defer p.catchPanic(p.arg, verb, "Error")
p.fmtString(v.Error(), verb)
return
case Stringer:
handled = true
defer p.catchPanic(p.arg, verb, "String")
p.fmtString(v.String(), verb)
return
}
}
}
return false
}
文章来源:https://blog.csdn.net/ppdouble/article/details/135228979
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!