In Go, Given an interface{} in which I know what interface it implements, how can I convert to it

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

In Go, Given an interface{} in which I know what interface it implements, how can I convert to it

问题

我目前的问题是,我正在实现数据结构,并为它们编写迭代器。我为我的数据结构、迭代器和所有其他所需对象编写了可见接口。在后台,我有具体的实现,希望将其隐藏起来,不让最终用户看到。

这就要求我的许多函数返回interface{}对象,以便我可以存储任何类型的对象(并将验证留给最终用户)。

我遇到的一个问题是,我要遍历一个图。我的图实现的迭代器返回一个具体的顶点类型,但Iterator接口返回interface{}。由于最终用户只能使用基本的Vertex接口,我必须尝试将其转换为Vertex接口,以便他们可以使用它。

以下是我目前能想到的最简单的例子,说明了我的问题:

package main

import (
	"fmt"
	"strconv"
)

type Base interface {
	Required() string
}

type Concrete struct {
	_data int
}

func (con *Concrete) Required() string {
	return strconv.Itoa(con._data)
}

func convert(val interface{}) *Base {
	if con, ok := val.(*Base); ok {
		return con
	}
	return nil
}

func main() {
	conc := new(Concrete)
	conc._data = 5

	base := convert(conc)

	fmt.Println(base)
}

在上面的代码中,我真的希望convert函数能将类型转换为*Base。但是,convert函数将返回nil值,而不是我希望的可爱的值。


编辑:删除了未使用的代码,我以为我已经删除了,但看来没有。

英文:

My current problem is that I am implementing data-structures and I have written iterators for them. I have visible interfaces for my data-structures, iterators, and all other required objects. In the back I have concrete implementations which I wish to hide from the end user.

This requires many of my functions to return interface{} objects so that I can store any type of object (and leave validation up to the end-user).

One problem I have is that I iterate over a Graph. My iterator{} for my graph implementation returns a concrete vertex type but the Iterator interface returns interface{}. Since the end-users can only my base Vertex interface I have to try to convert to a Vertex interface so they can use it.

Here is the smallest example that I could think of at this point which illustrates my issue:

package main

import (
	"fmt"
	"strconv"
)

type Base interface {
	Required() string
}

type Concrete struct {
	_data int
}
func (con *Concrete) Required() string {
	return strconv.Itoa(con._data)
}

func convert(val interface{}) *Base {
	if con,ok := val.(*Base); ok {
		return con
	}
	return nil
}

func main() {
	conc := new(Concrete)
	conc._data = 5
	
    base := convert(conc)
	
	fmt.Println(base)
}

In the code above I really wish that convert would convert the type to *Base. The function convert will return the value nil instead of the lovely value I wish it to be.


Edit: Removed unused code, I thought I had already removed it but I guess not.

答案1

得分: 0

现在我已经完成了这个长篇解释,我有一个想法并找到了解决方案:

func convert(val interface{}) Base {
    if con, ok := val.(Base); ok {
        return con
    }
    return nil
}

不要尝试将其转换为指针,而是只转换为Base接口。

我不确定为什么会这样。当我在convert函数内部执行reflect.TypeOf(val)时,输出结果是:

*main.Concrete

我希望其他人会发现这个有用,并且希望有人能回答这个答案中的为什么部分。

英文:

Now that I have finished writing this long explanation I had an idea and figured out the solution:

func convert(val interface{}) Base {
	if con,ok := val.(Base); ok {
		return con
	}
	return nil
}

Don't try to cast to a pointer but rather just the Base interface.

I am not sure why this is the case. When I do reflect.TypeOf(val) inside of convert it gives the output

*main.Concrete

I hope that other people find this useful and that someone else can answer the why portion of this answer.

huangapple
  • 本文由 发表于 2015年8月31日 11:38:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/32303655.html
匿名

发表评论

匿名网友

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

确定