Go: 本地结构的包函数接口

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

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&lt;current {
			max = at-1
		} else {
		if lookup&gt;current {
			min = at+1
			} else {
				return at, f.Value[at], true // found
			}
		}
		if min&gt;max {
			return 0, 0, false // doesn&#39;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&lt;current {
            max = at-1
        } else {
        if lookup&gt;current {
            min = at+1
            } else {
                return at, f.Value(at), true // found
            }
        }
        if min&gt;max {
            return 0, 0, false // doesn&#39;t exist
        }
        at = (max+min)/2
    }
}

and main

package main

import (
    &quot;path/to/binsearch&quot;
)

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))
}

playground

英文:

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 &lt; current {
			max = at - 1
		} else {
			if lookup &gt; current {
				min = at + 1
			} else {
				return at, vals[at], true // found
			}
		}
		if min &gt; max {
			return 0, 0, false // doesn&#39;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 := &amp;mystruct{[]uint{12, 123456, 13}, []uint{1,2,3}}
	fmt.Println(Get(test, 123456))
}

<kbd>playground</kbd>

答案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 := &amp;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 包中看到接口的示例,比如 StringerScanner,或者更接近你的例子,在 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).

huangapple
  • 本文由 发表于 2014年8月5日 21:40:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/25140274.html
匿名

发表评论

匿名网友

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

确定