Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
As far as I can tell, when passing a function as an input into another function it must have an identical contract - not allowing for the ability to leverage interfaces as follows: (runnable example here: https://play.golang.org/p/LXvNgziDdgp)
package main
func main() {
foo(processS1)
}
type I1 interface {
bar()
}
type S1 struct {
}
func (s1 S1) bar() {
}
func processS1(s S1) {
}
func foo(func(I1)) {
}
from a type-system perspective, the assumed issue is that a function type is passed, and not an interface. but, I can't see what the issue would be with allowing the type system to infer the relationship here. I believe I've seen this in other languages.
Any reason as to why Go can't/won't support this?
In short the relationship you've defined there is not valid in any typed language.
You've defined foo as a function that takes a type func(I1). func(S1) is a different type. The complexities of the relationships between these types is more complex than simple inheritance. The golang team has chosen simplicity over solving for function type and signature matching.
One way these complexities become apparent is you've actually defined the relationship backwards. Imagine there was an struct s2 that also implemented I1. Also, s1 had a method baz().
If foo passed in S2{} to the function parameter it would implement I1, but processS1 would call a function that doesn't exist on the passed in struct.
runnable: https://play.golang.org/p/EvwQpCXhqTb
Even if you swapped the types (https://play.golang.org/p/ItUx5pRJ6-g), which would be able to run without panics, it still wouldn't work in golang. As to why golang doesn't try to solve these problems, I'm not sure you'll get a satisfactory answer. The team responds to these kind of questions with general philosophical views such as:
The simplicity of method matching is a feature of the language.
I do think your question here does help justify that view though. It's a complex the problem is hard to reason about. It's easier to just not solve it than add additional complexity.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
In OCaml, there is a construct called univ_map.t, which allows you to map from 'a Type_equal.Id.t values to 'as. Here is an example.
Is there a construct that would allow me to do something similar in Rust? I know in OCaml they are implemented with open variants, which I don't believe Rust has.
I'm not familiar with OCaml, but looking at the docs:
Univ_map: Universal/heterogeneous maps [...] useful for storing values of arbitrary type in a single map [...] built on top of Univ.
Univ: An extensible universal variant type. Every type id corresponds to one branch of the variant type.
The closest thing that Rust has that sounds like Univ is the Any trait, which is designed to represent any type (with exceptions). However, there is no standard type for storing a collection of Anys that is accessed by its TypeId. From looking how popular crates handle this, its usually a bespoke wrapper around HashMap<TypeId, Box<dyn Any>> or similar. I hope I've understood correctly.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I am currently learning go after C++. I just get stuck every time while facing interface.
e.g:
s := []interface{}{"a", "b", "c"}
How string could be an interface?
I am not getting in what sense interface is introduced in go. There are many more doubts regarding interface.
Answer to the above question and especially providing some learning resources regarding interface would be great.
Thanks in advance :)
By definition, an interface is defined as a set of method signatures. So it is used to indicate which methods should be implemented by another type. If the interface doesn't specify any method signatures in the interface declaration body then any valid type can be of the type of that interface since there are no prerequisites of being that interface.
In your example, the slice contains a type of interface{} meaning any type can be a valid candidate as the slice input.
s := []interface{}{"a", 1, false}
https://tour.golang.org/methods/9 is a good place for exploring and learning go.
You can think of an interface as a container that holds a value and the type of that value.
When you define your own interfaces the compiler will ensure that the values you assign (store in the interface) have methods that match what you specified in your interface definition.
Empty interfaces, interface{}, have no methods and can therefore store any value since there are no expectations for the existence of any particular methods.
If you have not already, check the section on interfaces in A Tour of Go.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
As in java8:
someList.stream().map(e->e.getXXX()).toList()
For example, I have a Student array/slice, and the struct Student contains properties like Id, Name, and so on.
I want to extract all Ids into a NEW array/slice with one-line code like java8 as mentioned above, instead of range. Is there is an example?
Currently there is not an easy, builtin way to do this. Although Go has first-class functions and lexical closure, it's not possible to write a function like map that will operate on arbitrary types in the way you want. (Also, there's no compact lambda syntax, but I consider that a relatively minor issue).
Instead, you have to do one of the following:
Operate on interface{}. While this would let you write a func map([]interface{}, func(interface{})interface{}) []interface{}, you lose compile-time type safety, you lose performance, and a []interface{} is not a []string (or whatever the type is of the field you wanted to fetch), nor can you even type-assert it to one, so working with the result is cumbersome.
Use code-generation. There are libraries out there that will generate map/filter/etc. code for you, specialized to given types, so that none of the disadvantages of #1 apply. And Go ships with a Go parser in the standard library, so most code generators are fairly robust. But code generation is a separate build step, hampers debuggability, and can hurt the clarity of code.
Just live with boilerplate, writing lots of loops, and forget about trying to achieve functional style.
Wait for Go 1.18 to bring generics, which should make libraries of functional idioms a lot more practical.
Most experienced Go users would recommend approach #3, and so do I (reluctantly).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
So I'm trying to port a package from "C" that implements AVL trees. It's an embedded implementation, so the AVL structure is embedded in the structure the application defines.
All of the internal code in the AVL package uses type casting, so if, for example, you put the AVL header at the beginning of your structure, what you pass to the AVL routine is something like
(struct avl *)&foo
where foo is your application structure.
As I understand it, GO won't let you do this (not without awful perversions which, as I understand it, are not supported, nor safe.)
That said, here's what I came up with: I added a field to the AVL structure as
owner interface{}
I then added a parameter to avl_tree_insert() as
owner interface{}
That parameter is a pointer to the beginning of the application structure, so something like this is done:
avl_tree_insert(root, &mystruct.avl, &mystruct, cmp_func)
avl_tree_insert then stores the owner interface in the corresponding field in its structure. Routines that look up or traverse the tree return, as before, an AVL node pointer, and the client then does
nodep = avlp.owner.(*mystruct)
and is good to go. This all works, but I can't help but wonder if there is a better way? Thanks!
A better way would be to use interfaces:
type AVLTreeNode interface {
// functions related to tree links, etc
}
type nodeImpl struct {
// Implements AVLTreeNode
}
// myNode embeds nodeimpl, so it is an AVLTreeNode
type myNode struct {
nodeImpl
// otherFields
}
This allows you to write tree management functions using AVLTreeNode interface, and then you can use type assertions to access the concrete structure itself.
avl_tree_insert(root, &mystruct, cmp_func)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
In some Golang Tips said that: small object should pass by value and big object should pass by reference.
But how big object is small object?
If a struct has 10+ Fields. should it pass by value?
As you see from the discussion it is "hard" to understand when to use a pointer or a reference. If you are learning the Golang I suggest to use this approach to decide when to use pointer or reference:
I need to use a struct only for read purpose
In this case I suggest to use a pointer to a struct, that's for performance reason (copy a struct is a time consuming operation as you can tell, no matter if is a "big" struct or a small one).
I need to use a struct on multiple function each one write something on the struct but the various function should be no influence each other
In this case you should pass the struct as reference.
I need to use a struct on multiple function each one write something on the struct and the various function should be use the result of previous function
In this case you should pass the struct by pointer.
As you can see this approach avoids to think about the "dimension" of the struct and focus on the use of the struct, I think this is a better approach because is not always easy to define the dimension of a struct.