I can only give the opinion of someone who's new to the language, but maybe 
that is helpful for me to describe the learning journey a bit.
I'd seen references (hehe) to maps and slices "acting like pointers" and 
thus weren't costly to be passing around directly into functions, and so I 
went to look for some official clarification.

I found that FAQ, which seemed to answer my question exactly: Maps and 
slices act like pointers, copying them doesn't copy the data they point to. 
Interfaces do not, if you copy them you'll be copying whatever is "inside" 
them.

Maybe I read it that way because I went into it with that notion, but to me 
I think the most common case of someone reading this question is because 
they're asking themselves "So what exactly is expensive to copy?", to which 
the question replies "Concrete values and interfaces can be expensive, 
pointers/maps/slices aren't"


But as well, I don't know how to improve it, what it says is true, and the 
fact that in the current implementation the interface is always a pair of 
words is just that, an implementation detail.
And I'm probably overthinking it, but I in general try not to rely in 
implementation details when I write code, but perhaps that is not the Go 
mindset that I should be taking.
If in some C implementations you could pass a struct into a function 
without copying it (say, if the compiler could verify you were only reading 
it) , I would still indirect it with a pointer to account for the other 
compilers where such an operation is expensive.

Is it common in Go to target the "current implementation" when reasoning 
about the performance of a program?
On Sunday, June 6, 2021 at 9:27:50 AM UTC+1 Rob 'Commander' Pike wrote:

> Can you explain the trap? I don't pick up that vibe, but I may be the 
> author of that paragraph. Plus there is no such thing as a big interface. 
> In the current implementation, all interfaces are the same size - a pair of 
> words. You may still have a misapprehension.
>
> Try the first half of this article I know I wrote: 
> https://blog.golang.org/laws-of-reflection.
>
> I recently translated a substantial C library into Go, and watching all 
> the pointers disappear, at least syntactically (there were still slices), 
> was marvelous.
>
> -rob
>
>
> On Sun, Jun 6, 2021 at 6:21 PM Joshua <joshua.o...@gmail.com> wrote:
>
>> Thanks all for the insights, I think a key takeaway for me is "Don't 
>> worry about it unless it's a problem", but it's also good to know that it 
>> (probably) isn't a problem!
>>
>> I'm glad at least the semantics are the same, and I guess I'll cross the 
>> performance bridge if I ever come to it and someone tries to compile my 
>> code with an alternative/older compiler.
>>
>> The FAQ [https://golang.org/doc/faq#pass_by_value] that raised this 
>> question for me still seems to be technically correct, but I will say the 
>> text definitely gives off a "If you're coming from C, pass big interfaces 
>> as pointers" vibe:
>>
>> "Map and slice values behave like pointers: they are descriptors that 
>> contain pointers to the underlying map or slice data. Copying a map or 
>> slice value doesn't copy the data it points to. Copying an interface value 
>> makes a copy of the thing stored in the interface value. If the interface 
>> value holds a struct, copying the interface value makes a copy of the 
>> struct. If the interface value holds a pointer, copying the interface value 
>> makes a copy of the pointer, but again not the data it points to."
>>
>> I wouldn't be surprised if other people from C/C++ fall into this trap, 
>> is there any chance the FAQ could be updated
>>
>> On Sunday, June 6, 2021 at 6:51:49 AM UTC+1 Amnon wrote:
>>
>>> I find that people coming to Go from C++ tend to use pointers everywhere 
>>> so as to avoid copying of structs.
>>> Once they get a bit more experience, they tend to use fewer pointers, 
>>> and are happier to pass structs around.
>>> Removing the "make everything a pointer" optimisation makes the code 
>>> simpler, and often actually makes it run faster
>>> as fewer values escape the heap. Allocation tends to dominate Go 
>>> runtime, so it is worth doing a bit more
>>> copying in order to get a bit less allocations. 
>>>
>>> On Saturday, 5 June 2021 at 22:34:09 UTC+1 axel.wa...@googlemail.com 
>>> wrote:
>>>
>>>> I would add that because the dynamic type of an interface value is not 
>>>> known at compile time, a variable of interface type really can't (in 
>>>> general) have a specific size.
>>>> If a function has an interface parameter, it must be possible to pass a 
>>>> value of *any* size to it. So even aside from what the current 
>>>> implementation does - any Go compiler must, in generalĀ¹, consider 
>>>> interfaces to be pretty-much-pointers.
>>>>
>>>> "in general" because a compiler can, of course, determine that in a 
>>>> certain scenario the value doesn't have to be packed and pass it as-is. 
>>>> This is an optimization sometimes called "devirtualization". But in the 
>>>> general case, a compiler can't prove that (e.g. the dynamic value in an 
>>>> interface could be determined by a random number generator), so it will 
>>>> always be an optimization and the default always has to be a form of 
>>>> boxing 
>>>> into a constantly sized shape.
>>>>
>>>> All of this is a good indication, from first principles, that you don't 
>>>> have to worry about the size of the dynamic value when passing it.
>>>>
>>>> What's more, in general you should trust the author of the package you 
>>>> are using to give you a reasonable implementation of an interface. You 
>>>> shouldn't worry what the dynamic type and value in an interface is, unless 
>>>> you have very good reason to care. In this case, unless you notice that 
>>>> your code is very slow if you don't use a pointer (that would be "a very 
>>>> good reason to care"), you shouldn't optimize it. And if you notice, you 
>>>> should open a bug against that package :) Though as established, you won't.
>>>>
>>>> On Sat, Jun 5, 2021 at 11:18 PM Ian Lance Taylor <ia...@golang.org> 
>>>> wrote:
>>>>
>>>>> On Sat, Jun 5, 2021 at 2:15 PM Joshua <joshua.o...@gmail.com> wrote:
>>>>> >
>>>>> > My question is general, but for ease of communicating I'll use the 
>>>>> specific example I ran into.
>>>>> >
>>>>> > I'm very new and for my first project I'm working with the bleve 
>>>>> library [https://pkg.go.dev/github.com/blevesearch/bleve].
>>>>> >
>>>>> > One function I need, "Open", returns an interface, "Index".
>>>>> >
>>>>> > I'd like to write my own function to act on this interface, and 
>>>>> given that I have no idea what the dynamic value of the interface is, my 
>>>>> first instinct is to rather pass a pointer to the returned interface into 
>>>>> my function.
>>>>> >
>>>>> > However, I see lots of calls of "If you're using pointers to 
>>>>> interfaces a lot, you probably don't understand them".
>>>>> >
>>>>> > Well, what am I not understanding?
>>>>> > My worry is that I have no idea what dynamic type is lurking within 
>>>>> the interface, if it's a pointer to a struct, then I obviously don't mind 
>>>>> passing it into my function.
>>>>> >
>>>>> > However if it is in fact a humungous 1GB struct, then I really 
>>>>> really don't want to be copying that around willy-nilly.
>>>>> >
>>>>> > Is there a way in general to avoid this, without looking at the 
>>>>> library source code to see what the actual concrete type is?
>>>>>
>>>>> In the current implementations a value of interface type is always a
>>>>> pair of pointers.  Even if the value of interface type happens to
>>>>> refer to a 1GB struct, copying the interface value, including passing
>>>>> it to a function or returning it from a function, always just copies
>>>>> two pointers.
>>>>>
>>>>> Ian
>>>>>
>>>>> -- 
>>>>> You received this message because you are subscribed to the Google 
>>>>> Groups "golang-nuts" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send 
>>>>> an email to golang-nuts...@googlegroups.com.
>>>>> To view this discussion on the web visit 
>>>>> https://groups.google.com/d/msgid/golang-nuts/CAOyqgcUuv_qrrG8%3DdCQZv0%2BrKbnbW60XdOCwjp8M3EdOCxCNkw%40mail.gmail.com
>>>>> .
>>>>>
>>>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com.
>>
> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/a891bbf5-9426-49b3-89c6-f185fe047b5en%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/a891bbf5-9426-49b3-89c6-f185fe047b5en%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/ae12bea1-f872-429e-b65a-ac05a50bbba5n%40googlegroups.com.

Reply via email to