英文:
Go: Package Function Interface for Local Struct
问题
我有一个棘手的问题,我不确定Go语言是否能够解决。基本上,我正在编写一个实现简单二分查找的包,我希望返回一个由用户定义的结构体的值,也就是说不在包内定义。
因此,我希望包内有一个函数可以分配给在package main
中定义的结构体。
在包内,二分查找的函数如下:
package binsearch
func (f *SomeStruct) Get(lookup uint) (int, uint, bool) {
min := 0
max := len(f.Key)-1
at := max/2
for {
current := f.Key[at]
if lookup<current {
max = at-1
} else {
if lookup>current {
min = at+1
} else {
return at, f.Value[at], true // found
}
}
if min>max {
return 0, 0, false // doesn't exist
}
at = (max+min)/2
}
}
然后在main
函数中,可以这样写:
package main
type mystruct struct {
Key []uint
Value []uint
}
func main() {
test := new(mystruct)
// 然后在这里添加一些数据
i, value, ok := test.Get(12345)
}
我需要在package main
中定义binsearch.Get
函数应用于mystruct
。这种做法可行吗?
英文:
I have a tricky issue which I'm not sure is possible with Go, basically I'm writing a package that implements a simple binary search, which I want to return a value of a struct which is defined by the user, i.e. not in the package.
So effectively I want a function in the package which can be assigned to a struct that is defined locally, that is to say in package main
.
So in the package is the function for binary search:
package binsearch
func (f *SomeStruct) Get(lookup uint) (int, uint, bool) {
min := 0
max := len(f.Key)-1
at := max/2
for {
current := f.Key[at]
if lookup<current {
max = at-1
} else {
if lookup>current {
min = at+1
} else {
return at, f.Value[at], true // found
}
}
if min>max {
return 0, 0, false // doesn't exist
}
at = (max+min)/2
}
}
And then in main something like:
package main
type mystruct struct {
Key []uint
Value []uint
}
func main() {
test := new(mystruct)
// Then add some data here
i, value, ok := test.Get(12345)
}
Somehow I need to define in package main
that the binsearch.Get
function should be applied to mystruct
. Is this possible?
答案1
得分: 3
这是使用接口的示例代码:
package binsearch
type Searchable interface {
Key(pos int) uint
Value(pos int) uint
Len() int
}
func Get(s Searchable, lookup uint) (int, uint, bool) {
min := 0
max := s.Len()-1
at := max/2
for {
current := s.Key(at)
if lookup<current {
max = at-1
} else {
if lookup>current {
min = at+1
} else {
return at, s.Value(at), true // 找到了
}
}
if min>max {
return 0, 0, false // 不存在
}
at = (max+min)/2
}
}
和主函数:
package main
import (
"path/to/binsearch"
)
type mystruct struct {
key []uint
value []uint
}
func (m *mystruct) Key(pos int) uint {
return m.key[pos]
}
func (m *mystruct) Value(pos int) uint {
return m.value[pos]
}
func (m *mystruct) Len() int {
return len(m.key)
}
func main() {
test := new(mystruct)
// 然后在这里添加一些数据
i, value, ok := binsearch.Get(test, 12345)
}
英文:
Here is what it would look like using interfaces:
package binsearch
type Searchable interface {
Key(pos int) uint
Value(pos int) uint
Len() int
}
func Get(s Searchable, lookup uint) (int, uint, bool) {
min := 0
max := s.Len()-1
at := max/2
for {
current := s.Key(at)
if lookup<current {
max = at-1
} else {
if lookup>current {
min = at+1
} else {
return at, f.Value(at), true // found
}
}
if min>max {
return 0, 0, false // doesn't exist
}
at = (max+min)/2
}
}
and main
package main
import (
"path/to/binsearch"
)
type mystruct struct {
key []uint
value []uint
}
func (m *mystruct) Key(pos int) uint {
return m.key[pos]
}
func (m *mystruct) Value(pos int) uint {
return m.value[pos]
}
func (m *mystruct) Len() int {
return len(m.key)
}
func main() {
test := new(mystruct)
// Then add some data here
i, value, ok := binsearch.Get(test, 12345)
}
答案2
得分: 1
不,你需要使用一个接口并在mystruct
上定义它。
type BinarySearchable interface {
Keys() []uint
Values() []uint
}
func Get(bs BinarySearchable, lookup uint) (int, uint, bool) {
keys := bs.Keys()
vals := bs.Values()
min := 0
max := len(keys) - 1
at := max / 2
for {
current := keys[at]
if lookup < current {
max = at - 1
} else {
if lookup > current {
min = at + 1
} else {
return at, vals[at], true // found
}
}
if min > max {
return 0, 0, false // doesn't exist
}
at = (max + min) / 2
}
}
type mystruct struct {
keys []uint
values []uint
}
func (ms *mystruct) Keys() []uint {
return ms.keys
}
func (ms *mystruct) Values() []uint {
return ms.values
}
func main() {
test := &mystruct{[]uint{12, 123456, 13}, []uint{1,2,3}}
fmt.Println(Get(test, 123456))
}
英文:
No, you will have to use an interface and define it on your mystruct
.
type BinarySearchable interface {
Keys() []uint
Values() []uint
}
func Get(bs BinarySearchable, lookup uint) (int, uint, bool) {
keys := bs.Keys()
vals := bs.Values()
min := 0
max := len(keys) - 1
at := max / 2
for {
current := keys[at]
if lookup < current {
max = at - 1
} else {
if lookup > current {
min = at + 1
} else {
return at, vals[at], true // found
}
}
if min > max {
return 0, 0, false // doesn't exist
}
at = (max + min) / 2
}
}
type mystruct struct {
keys []uint
values []uint
}
func (ms *mystruct) Keys() []uint {
return ms.keys
}
func (ms *mystruct) Values() []uint {
return ms.values
}
func main() {
test := &mystruct{[]uint{12, 123456, 13}, []uint{1,2,3}}
fmt.Println(Get(test, 123456))
}
答案3
得分: 1
你可以不使用接口来完成这个任务,但是你需要将你的mystruct
类型转换为binsearch.SomeStruct
类型。这是因为binsearch.Get
函数的接收者是指向binsearch.SomeStruct
类型的指针,而在这种情况下,Go语言不会自动为你转换类型。
虽然没有通用的方法来完成这个任务,但是针对你的应用程序,可能会像这样实现:
s := &SomeStruct{}
copy(test.Key, s.Key)
copy(test.Value, s.Value)
i, value, ok := s.Get(12345)
英文:
You can do this without interfaces but you have to convert your mystruct type into a binsearch.SomeStruct type. This is because the binsearch.Get function is defined to take a pointer to a binsearch.SomeStruct as a receiver and Go doesn't autconvert types for you in this situation.
There is no general way to do this, but one specific to your application might look like this:
s := &SomeStruct{}
copy(test.Key, s.Key)
copy(test.Value, s.Value)
i, value, ok := s.Get(12345)
答案4
得分: 0
你描述的方式是不可能的。Golang使用的是接口(interface)的概念:你可以定义一组给定结构体必须实现的方法。
type Fooer interface {
Bar(i int)
}
然后,你可以定义一个函数或方法,以该类型的变量作为参数,并使用定义的方法集来完成其工作。
func Foo(a Fooer) {
// 在这里使用 Bar() 方法做你的事情
}
惯例是给接口命名以 -er
结尾。你可以在 fmt
包中看到接口的示例,比如 Stringer
和 Scanner
,或者更接近你的例子,在 sort
包中定义了一个名为 Interface
的接口(完整名称为 sort.Interface
),这是对惯例的一种打破,但实际上比惯例更清晰,因为该包只有一个接口,并且该包是为了与该接口一起使用而构建的。
英文:
It is not possible in the way you described. What Golang use is the concept of interface: you define a set of methods that a given struct must implement.
type Fooer interface {
Bar(i int)
}
You can then define a function or method that will take a variable of this type as parameter, and use the defined set of methods to do its job.
func Foo(a Fooer) {
// Do you stuff here using the Bar() method
}
The convention is to give the interface a name ending in -er
. You can see examples of interfaces in the fmt
package with Stringer
and Scanner
, or closer to you example, in the package sort
which define an interface named Interface
(which full name is sort.Interface
, which is a break in the convention but actually cleaner than said convention given there is only one interface in the package and the package is built to work with this interface).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论