dongxu198714 2018-04-22 21:01
浏览 125

绑定到结构的Golang函数类型?

This might seem like a silly question, but I want to make a struct with a collection of functions, but the functions bind to the struct. I can sorta see that this is a cycle, but humor me with this example:

type FuncType func() error

type FuncSet struct {
  TokenVariable  int
  FuncTyper      FuncType
}

and I want to be able to create a function bound to the FuncSet type so it can operate on TokenVariable, thusly:

func (f *FuncSet) FuncType() error {
  f.TokenVariable = 100
  return nil
}

However, this changes the signature of the type (I can't find any information about type bindings as part of function type specifications) such that assigning this function to the struct element tells me this function/variable is not found.

I can see an easy work-around for this, by prefixing the parameters with a pointer to the struct type, it's just a bit ugly.

I looked around a little further and discovered that what I'm kinda looking for is like a closure in that it can be passed a variable from the immediate outer scope but... well, I'll be glad to be corrected about this absence of type binding in function types, but for now passing the pointer to the type looks like the way to go.

I think I found the solution:

type nullTester func(*Bast, uint32) bool

type Bast struct {
  ...
  isNull    nullTester
  ...
 }

func isNull(b *Bast, d uint32) bool {
  return d == 0
}

and then I can bind it to the type like this:

func NewBast() (b *Bast) {
  ...
  b.isNull = isNull
  ...
}

// IsNull - tests if a value in the tree is null
func (b *Bast) IsNull(d uint32) bool {
  return b.isNull(b, d)
}

It seems a bit hackish and I'm not sure what's going to happen in a second library that I will write that sets a different type for the uint32 parameter, but go vet is happy so maybe this is the correct way to do it.

It does seem to me that func types should really have a field in the grammar to specify a binding type, but maybe I just found a hack that sorta lets me do polymorphism. In calling programs all they will see is the nice exported function that binds to the type as planned and I get my readability as well as being able to retarget the base library to store a different type of data.

I think this is the proper solution. I just can't find anything that confirms or denies whether in a type Name func specification there is any way of asserting the type. It really should not match up, since the binding is part of the signature, but the syntax for type with functions does not appear to have this type binding.

My actual code is here, and you can see by looking at it what I am aiming to do: https://github.com/calibrae-project/bast/blob/master/pkg/bast/bast.go

The differences between the type of data the tree stores is entirely superficial, because it is intended to be primarily used for sorting unsigned integers of various lengths, and one important thing it needs to have is to be able to work from a, for example, 64 bit integer but sort only by the first or last half (as I have a bigger project that treats these hash values as coordinates in an adjacency list). In theory it could be used instead of a hash table lookup as well, with a low variance in time to find elements because of the binary tree structure.

It's not a conventional, reference-vector based tree, and the store itself is an array with an unconventional power of two mapping, a 'dense' tree, and the purpose above all, for implementing this way, is that when the tree is walked, as well as rotated, much of the time it is sequential blocks of memory being accessed which should make for a lot less cache misses than a conventional binary tree (and for which reason generally this type of application just uses some kind of sort like a bucket sort).

  • 写回答

1条回答 默认 最新

  • dougaodi8895 2018-04-23 16:29
    关注

    You could use an anonymous field with an interface that defines the method set that you want to use (that might change).

    Go playground here

    You'd define your interface

    type validator interface {
        IsRightOf(a, b interface{}) bool
    
        ... // other methods
    }
    

    and your type:

    type Bast struct {
        validator // anonymous interface field
    
        ... // some fields
    }
    

    Then you can access the methods of validator from the Bast type

    b := bast.New()
    b.IsRightOf(c, d) // this is valid, you do not need to do b.validator.IsRightOf(...)
    

    because validator is an interface you can change those methods how you like.

    评论

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况