为什么我不能在界面中访问此字段?

用户776942:

我试图更好地理解接口,而不是为什么s没有领域Width我的例子在这里

package main

import "fmt"

type shapes interface {
    setWidth(float64)
}

type rect struct {
    Width float64
}

func (r *rect) setWidth(w float64) {
    r.Width = w
}

var allShapes = map[string]shapes{
    "rect": &rect{},
}

func main() {
    r := &rect{}
    r.setWidth(5)
    fmt.Println(r.Width)  // this works
    for _, s := range allShapes {
        s.setWidth(7)
        fmt.Println(s.Width) // why not???
    }
}

为什么r有宽度但s没有宽度我得到的确切错误是:

s.Width undefined (type shapes has no field or method Width)
派'Oh'Pah:

shapes接口是*rect实现的对象,但不是具体类型*rect就像任何界面一样,它是一组允许任何满足其要求的类型通过的方法,例如给它添加临时访客标签以使其上楼。

例如,在Go的建筑物中,如果有一只猴子(或代表它的价值,它是一只海豚)可以行动并做人类可以做的一切,那么他可以越过警卫并上电梯。但是,这并不能使他从基因上成为人类。

Go是静态类型的,这意味着即使具有相同基础类型的两个类型在没有类型声明或有意识地转换类型的情况下也无法动态转换或强制转换为彼此。

var a int
type myInt int
var b myInt

a = 2
b = 3
b = a         // Error! cannot use a (type int) as type myInt in assignment.
b = myInt(a)  // This is ok.

和我一起想象一下这种情况:

type MyInt int
type YourInt int

type EveryInt interface {
        addableByInt(a int) bool
}

func (i MyInt) addableByInt(a int) bool {
    // whatever logic doesn't matter
    return true
}


func (i YourInt) addableByInt(a int) bool {
    // whatever logic doesn't matter
    return true
}

func main() {
    // Two guys want to pass as an int
    b := MyInt(7)
    c := YourInt(2)

    // Do everything an `EveryInt` requires
    // and disguise as one 
    bi := EveryInt(b)
    ci := EveryInt(c)

    // Hey, look we're the same! That's the closest
    // we can get to being an int!
    bi = ci          // This is ok, we are EveryInt brotherhood
    fmt.Println(bi)  // bi is now 2

    // Now a real int comes along saying
    // "Hey, you two look like one of us!"
    var i int
    i = bi           // Oops! bi has been made

    // ci runs away at this point

}

现在回到您的场景-想象一个*circle实现的实现shapes

type circle struct {
        Radius float64
}

func (c *circle) setWidth(w float64) {
        c.Radius = w
}

*circle完全可以通过,shapes但是它没有Width属性,因为它不是*rect接口不能直接访问基础类型的属性,而只能通过已实现的方法集进行访问。为了访问属性,需要在接口上进行类型断言,以便实例成为具体的类型:

var r *rect

// Verify `s` is in fact a `*rect` under the hood
if r, ok := s.(*rect); ok {
        fmt.Println(r.Width)
}

这就是为什么像Go这样的静态类型的语言总是比动态类型的语言快的原因的核心,而动态类型的语言几乎总是使用某种反射来为您动态处理类型强制。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么我不能在界面中使用默认方法?

为什么不能在SAXParser中打开此XML?

为什么不能在lambda中捕获此按引用('&this')?

为什么我不能在JavaScript中解析此json字符串?

为什么我不能在F#中打印此数组?

为什么我不能在HTML5数字字段中输入500?

为什么我不能在组件内访问道具?

为什么我不能在RStudio中获得此字符串?

为什么我不能在界面中创建默认方法?

为什么我的选择字段事件处理程序不能在Chrome / Android中工作?

为什么我不能在Redis中的此排序集上使用ZRANGEBYLEX?

为什么我不能在Vue中访问html canvas?

为什么我不能在Mirth中访问xml消息?

为什么我不能在批处理文件中运行此Powershell脚本?

为什么我不能在netlify中运行此脚本?

为什么我不能在声明中定义静态字段?

为什么我不能在Linux上终止此过程?

为什么我不能在班级中访问变量。Python

为什么我不能在PHP函数中访问我的私有变量?

为什么我不能在Yii中更新此模型?

为什么此“ if”不能在Java中执行?

为什么我不能在其他字段中重复使用“ Pikaday”日历?

为什么我不能在Swift中访问此数组的第二级?

为什么我不能在 PHP 7 中访问我的会话变量?

为什么我不能在批处理/ cmd 文件中的此代码中嵌套 if existing 语句

为什么我不能在 OCaml 中再次打印此输入?

为什么我不能在 CSS 中调整此图像的大小?

Nextcord,为什么我不能在@tasks.loop 中执行此操作?

为什么我不能在输入文本字段中输入?