- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我正在阅读 The Go Programming Language 中的类型断言 x.(T)
并且不理解它们。
我知道有不同的场景:
这是我不明白的:
我也用谷歌搜索过这个话题,但还是不明白。
最佳答案
一行:
x.(T)
asserts thatx
is not nil and that the value stored inx
is of typeT
.
x
是否为 nilx
持有的动态类型是什么x
中提取动态类型 t := x.(T)
=> t 是 T
类型;如果 x
为 nil,它会崩溃。
t,ok := x.(T)
=> 如果 x
是 nil 或不是 T
类型 => ok
是 false
否则 ok
是 true
并且 t
是 T
类型。
假设您需要计算 4 种不同形状的面积:圆形、正方形、矩形和三角形。您可以使用名为 Area()
的新方法定义新类型,如下所示:
type Circle struct {
Radius float64
}
func (t Circle) Area() float64 {
return math.Pi * t.Radius * t.Radius
}
对于 Triangle
:
type Triangle struct {
A, B, C float64 // lengths of the sides of a triangle.
}
func (t Triangle) Area() float64 {
p := (t.A + t.B + t.C) / 2.0 // perimeter half
return math.Sqrt(p * (p - t.A) * (p - t.B) * (p - t.C))
}
对于 Rectangle
:
type Rectangle struct {
A, B float64
}
func (t Rectangle) Area() float64 {
return t.A * t.B
}
对于 Square
:
type Square struct {
A float64
}
func (t Square) Area() float64 {
return t.A * t.A
}
这里有 Circle
,半径为 1.0,其他形状有边:
shapes := []Shape{
Circle{1.0},
Square{1.772453},
Rectangle{5, 10},
Triangle{10, 4, 7},
}
有趣!我们如何才能将它们全部收集到一个地方?
首先,您需要 Shape interface
将它们全部收集在一个 []Shape
形状的 slice 中:
type Shape interface {
Area() float64
}
现在你可以像这样收集它们:
shapes := []Shape{
Circle{1.0},
Square{1.772453},
Rectangle{5, 10},
Triangle{10, 4, 7},
}
毕竟,Circle
是一个 Shape
,Triangle
也是一个 Shape
。
现在您可以使用单个语句 v.Area()
打印每个形状的面积:
for _, v := range shapes {
fmt.Println(v, "\tArea:", v.Area())
}
所以 Area()
是所有形状之间的通用接口(interface)。现在,我们如何使用上面的 shapes
来计算和调用不常见的方法,例如三角形的角度?
func (t Triangle) Angles() []float64 {
return []float64{angle(t.B, t.C, t.A), angle(t.A, t.C, t.B), angle(t.A, t.B, t.C)}
}
func angle(a, b, c float64) float64 {
return math.Acos((a*a+b*b-c*c)/(2*a*b)) * 180.0 / math.Pi
}
现在是时候从上面的 Triangle
中提取 shapes
了:
for _, v := range shapes {
fmt.Println(v, "\tArea:", v.Area())
if t, ok := v.(Triangle); ok {
fmt.Println("Angles:", t.Angles())
}
}
我们使用 t, ok := v.(Triangle)
请求类型断言,这意味着我们要求编译器尝试将 v
类型的 Shape
转换为类型 Triangle
,这样如果成功, ok
将是 true
否则 false
,然后如果成功调用 t.Angles()
到计算三角形的三个角。
这是输出:
Circle (Radius: 1) Area: 3.141592653589793
Square (Sides: 1.772453) Area: 3.1415896372090004
Rectangle (Sides: 5, 10) Area: 50
Triangle (Sides: 10, 4, 7) Area: 10.928746497197197
Angles: [128.68218745348943 18.194872338766785 33.12294020774379]
以及整个工作示例代码:
package main
import "fmt"
import "math"
func main() {
shapes := []Shape{
Circle{1.0},
Square{1.772453},
Rectangle{5, 10},
Triangle{10, 4, 7},
}
for _, v := range shapes {
fmt.Println(v, "\tArea:", v.Area())
if t, ok := v.(Triangle); ok {
fmt.Println("Angles:", t.Angles())
}
}
}
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
type Triangle struct {
A, B, C float64 // lengths of the sides of a triangle.
}
type Rectangle struct {
A, B float64
}
type Square struct {
A float64
}
func (t Circle) Area() float64 {
return math.Pi * t.Radius * t.Radius
}
// Heron's Formula for the area of a triangle
func (t Triangle) Area() float64 {
p := (t.A + t.B + t.C) / 2.0 // perimeter half
return math.Sqrt(p * (p - t.A) * (p - t.B) * (p - t.C))
}
func (t Rectangle) Area() float64 {
return t.A * t.B
}
func (t Square) Area() float64 {
return t.A * t.A
}
func (t Circle) String() string {
return fmt.Sprint("Circle (Radius: ", t.Radius, ")")
}
func (t Triangle) String() string {
return fmt.Sprint("Triangle (Sides: ", t.A, ", ", t.B, ", ", t.C, ")")
}
func (t Rectangle) String() string {
return fmt.Sprint("Rectangle (Sides: ", t.A, ", ", t.B, ")")
}
func (t Square) String() string {
return fmt.Sprint("Square (Sides: ", t.A, ")")
}
func (t Triangle) Angles() []float64 {
return []float64{angle(t.B, t.C, t.A), angle(t.A, t.C, t.B), angle(t.A, t.B, t.C)}
}
func angle(a, b, c float64) float64 {
return math.Acos((a*a+b*b-c*c)/(2*a*b)) * 180.0 / math.Pi
}
另见:
For an expression x of interface type and a type T, the primaryexpression
x.(T)
asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion.
More precisely, if T is not an interface type, x.(T) asserts that thedynamic type of x is identical to the type T. In this case, T mustimplement the (interface) type of x; otherwise the type assertion isinvalid since it is not possible for x to store a value of type T. IfT is an interface type, x.(T) asserts that the dynamic type of ximplements the interface T.
If the type assertion holds, the value of the expression is the valuestored in x and its type is T. If the type assertion is false, arun-time panic occurs. In other words, even though the dynamic type ofx is known only at run time, the type of x.(T) is known to be T in acorrect program.
var x interface{} = 7 // x has dynamic type int and value 7
i := x.(int) // i has type int and value 7
type I interface { m() }
var y I
s := y.(string) // illegal: string does not implement I (missing method m)
r := y.(io.Reader) // r has type io.Reader and y must implement both I and io.ReaderA type assertion used in an assignment or initialization of thespecial form
v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)yields an additional untyped boolean value. The value of ok is true ifthe assertion holds. Otherwise it is false and the value of v is thezero value for type T. No run-time panic occurs in this case.
问题:当 T 是 x.(T)
而不是具体类型时,断言 interface{}
返回什么?
回答:
It asserts that x is not nil and that the value stored in x is of type T.
例如这个 panic (编译:成功,运行:panic: interface conversion: interface is nil, not interface {}
):
package main
func main() {
var i interface{} // nil
var _ = i.(interface{})
}
这有效(运行:OK):
package main
import "fmt"
func main() {
var i interface{} // nil
b, ok := i.(interface{})
fmt.Println(b, ok) // <nil> false
i = 2
c, ok := i.(interface{})
fmt.Println(c, ok) // 2 true
//var j int = c // cannot use c (type interface {}) as type int in assignment: need type assertion
//fmt.Println(j)
}
输出:
<nil> false
2 true
注意:这里 c
是 interface {}
类型而不是 int
。
package main
import "fmt"
func main() {
const fm = "'%T'\t'%#[1]v'\t'%[1]v'\t%v\n"
var i interface{}
b, ok := i.(interface{})
fmt.Printf(fm, b, ok) // '<nil>' '<nil>' '<nil>' false
i = 2
b, ok = i.(interface{})
fmt.Printf(fm, b, ok) // 'int' '2' '2' true
i = "Hi"
b, ok = i.(interface{})
fmt.Printf(fm, b, ok) // 'string' '"Hi"' 'Hi' true
i = new(interface{})
b, ok = i.(interface{})
fmt.Printf(fm, b, ok) // '*interface {}' '(*interface {})(0xc042004330)' '0xc042004330' true
i = struct{}{}
b, ok = i.(interface{})
fmt.Printf(fm, b, ok) // 'struct {}' 'struct {}{}' '{}' true
i = fmt.Println
b, ok = i.(interface{})
fmt.Printf(fm, b, ok) // 'func(...interface {}) (int, error)' '(func(...interface {}) (int, error))(0x456740)' '0x456740' true
i = Shape.Area
b, ok = i.(interface{})
fmt.Printf(fm, b, ok) // 'func(main.Shape) float64' '(func(main.Shape) float64)(0x401910)' '0x401910' true
}
type Shape interface {
Area() float64
}
关于go - 解释 Go 中的类型断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58052684/
我正在使用 go 图表库 https://github.com/wcharczuk/go-chart制作条形图。我面临的问题是标签值很长,我想将文本旋转 45 度以显示完整文本 我喜欢显示的日期格式是
我在构建一个非常简单的通过 cgo 调用 c 代码的 go 程序时遇到了问题。我的设置: $: echo $GOPATH /go $: pwd /go/src/main $: ls ctest.c
没有 C 的背景,只有 Go 的“初学者”经验,我正在尝试弄清楚 main.go 是实际需要的还是只是一个约定。 我想创建一个简单的网络 API,但有人可以为我澄清一下吗? 最佳答案 main.go
我read从 Go 1.4 开始,Go 运行时是用 Go 本身编写的(而不是用 C)。 这怎么可能?如果 Go 程序在运行时之上运行,并且运行时是 Go 程序,那么运行时是否在自身之上运行? 最佳答案
这是“Go 之旅”中的代码示例 Range and Close : package main import ( "fmt" ) func fibonacci(n int, c chan int
给定以下 go.mod 文件: module foo go 1.12 require ( github.com/bar/baz v1.0.0 github.com/rat/cat v1
我有一个 CI/CD 管道,它需要跨平台并与几个不同的管理程序一起工作。为了不必更改 Windows 和 Linux 的构建任务,我认为 Go 将是编写一次代码并在任何地方运行的好方法。然而,考虑到
我有一个 Dockerfile,用于使用 go build 编译 Go 应用程序。我进行了研究,确实建议将 go build 用于生产。 但是我找不到正确的答案来解释为什么。 我了解 go run 创
我尝试在命令提示符#Go lang 中运行该程序-但是当我键入运行“go run hello.go”命令时,我开始了 CreateFile hello.go:The system cannot fin
我正在使用“Go 编程语言”一书学习 Go。第一章介绍os.Open用于读取文件的模块。我尝试打开如下所示的 go 文件。 f, err = os.Open("helloworld.go") 我收
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题?通过 editing this post 添加详细信息并澄清问题. 2年前关闭。 Improve this
为了解决我对 goroutine 的一些误解,我去了 Go 操场跑了 this code : package main import ( "fmt" ) func other(done cha
这个问题在这里已经有了答案: Evaluate/Execute Golang code/expressions like js' eval() (5 个回答) 1年前关闭。 对于任何 go 程序,我想
这是我基本上试图从路径打印基准的代码。 这意味着,如果用户输入“/some/random/path.java”,则输出将为“path”。同样,如果用户arg为“/another/myapp.c”,则输
$ go version 1.13.3 我的文件夹结构如下: GOPATH +---src +--- my-api-server +--- my-auth-server
这个问题在这里已经有了答案: How to embed file for later parsing execution use (4 个答案) What's the best way to bun
我觉得这有点奇怪,为什么这段代码不起作用? package main import "fmt" func main() { var i, j int = 1, 2 k
go编译器执行完如下命令后的可执行文件存放在哪里? $> go run file.go 最佳答案 在 /tmp 文件夹中,如果您使用的是 unix 机器。 如果您使用的是 Windows,则在 \Us
我目前正在开始使用 Go,并且已经深入研究了有关包命名和工作区文件夹结构的注意事项。 不过,我不太确定如何根据 Go 范式正确组织我的代码。 这是我当前的结构示例,它位于 $GOPATH/src 中:
假设我有一个接受用户输入的 Lua 程序,而该输入恰好是有效的 Lua 源代码。这是在程序仍在运行时进行清理、编译和执行的。 Go 是否(或将)实现这样的事情? 最佳答案 我认为以下两个项目之间有足够
我是一名优秀的程序员,十分优秀!