Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Gopher Tricks (golang.org)
101 points by rjammala on Aug 21, 2015 | hide | past | favorite | 36 comments


I swear, one of these days I'll implement a gopher server and client in go just out of spite.

Every time I read a link mentioning "gopher" I expect it to be a neat hack based on the obsoleted protocol.


By the author of the linked slide deck (Andrew Gerrand): https://github.com/nf/gogopherd/

By Brad Fitzpatrick (another Go team member): https://code.google.com/p/gogopherd/



I swear, one of these days I'll implement a gopher server and client in go just out of spite.

I've been playing around with Gopher a bit lately. I installed eLinks just to have a Gopher client. I've even been thinking about setting up gopher://gopher.fogbeam.com to serve content over Gopher protocol. :-)

Every time I read a link mentioning "gopher" I expect it to be a neat hack based on the obsoleted protocol.

Came here to say the same thing. Every time I see one of these headlines, I expect something about Gopher[1], not Golang.

[1]: https://en.wikipedia.org/wiki/Gopher_(protocol)


Reading over that article i find myself wondering if Gopher would be a good fit for a Freenet like system.


Yes! Bring back gopher!


1a. Install Overbite (http://gopher.floodgap.com/overbite/)

OR

1b. Install Lynx or eLinks

2. goto gopher://gopher.floodgap.com


In practice I've not found anonymous structs too useful. You end up being very verbose and then discover you'd have been better off with a named type anyway.

It'd be nice to have a shorthand which mixed the type definition and assignment into a single line so you could do something like:

S := { x int : 1, y int : 2 }

Or even

S:= { x := 1, y := 2 }


I use them extensively for test cases (`cases := []struct{...} { ... }`) as mentioned in the slides. Also sometimes to marshal/unmarshal one-off json or xml payloads.


I get the feeling the Go language creators defined the Go language syntax in many cases so that it explicitly looks different than the corresponding C syntax. Why?

(Yes, I know Rob's and Ken's history with regards to C.)


Lucky for you there's an article explaining exactly that: http://blog.golang.org/gos-declaration-syntax

---

I like the map. Here's the rules for Conway's Game of Life as a nested map:

    var cgol = map[state]map[int]state{
        alive: {
            0: dead,
            1: dead,
            2: alive,
            3: alive,
            4: dead,
            5: dead,
            6: dead,
            7: dead,
            8: dead,
        },
        dead: {
            0: dead,
            1: dead,
            2: dead,
            3: alive,
            4: dead,
            5: dead,
            6: dead,
            7: dead,
            8: dead,
        },
    }


That type declaration is easily as unreadable as any "pointer to function returning pointer" declaration in C.


What nonsense, where is there any remote ambiguity? Where is it even slightly unreadable?


Reads pretty clearly left-to-right to me:

map[state]map[int]state -> a map of state keys pointing to maps of int keys pointing to states


    "map of int to string"
     map   [int]   string
    
    "map of state to map of int to state"
     map   [state]   map   [int]   state
In Rich Hickey terminology, it seems people reject that it is simple (non-interwoven) because it does not strike them as easy (familiar / close to hand).

( ...Any excuse to link to this excellent presentation: http://www.infoq.com/presentations/Simple-Made-Easy )


I read that as arrogance.

Before C, naturally no-one knew C.

Before Go though, tens of millions know C.

They are casually throwing away all of that familiarity in the name of elegance. I think this is what might mean that Go doesn't "win".


For someone who can already program, such things are trivial to learn.

If you class doing basic design work and taking time to document it as "arrogance" then I'm afraid you may be suffering from negative mindset.


It's important to note that a lot of C programmers don't really understand the C declaration syntax anyway. Most are familiar with the simple cases, very few are familiar with how to declare complex types.

I can barely read this: void (signal(int, void (fp)(int)))(int);

I can read this easily: func signal(int, func(int)) func(int)


> throwing away all of that familiarity in the name of elegance

That looks like a good deal to me! :)


Well shit, how come I've never seen anonymous structs before.

That's pretty cool.


Finding out Go had anonymous structs is what lead me to start learning Go.


What about finding out it didn't have generics?


This trick fits more into the "prank" category.

    package main
    
    import "fmt"
    
    // <Add one short line of valid Go code here>
    
    func main() {
    	var n int = 1
    	fmt.Println(n)
    }
    
    Compiler: "prog.go:8: cannot use 1 (type int) as type int in assignment"
Here's a trick that I expected to work but doesn't. Would be interested to hear the rationale if anyone knows it.

    m := map[[]int]int{}


> Here's a trick that I expected to work but doesn't. Would be interested to hear the rationale if anyone knows it.

    m := map[[]int]int{}
... will not work, because []int is a slice—that is, a pointer to an array of undetermined state (also technically some more metadata like an offset/size). Think of a slice as a "view" into an array, which does not necessarily need to remain static. A slice does not necessarily "own" the data it's providing a view of; you can have many slices of one array.

    m := map[[3]int]int{}
will work, because [3]int is an actual array.

To recap:

    a := [3]int{1,2,3}  // Array
    b := a[:2]          // Slice
    var c []int = a[:]  // Slice
    var d [3]int        // Array
    copy(d[:], c)       // Copy to (a slice of an) array from slice


Well, you could take the position that types that permit modification should not be allowed as keys but then you would not allow arrays as keys, which Go does allow. Check this out: http://play.golang.org/p/kocW1BjTco

Another approach to take, which I think could be quite useful, is that if you use something modifiable as a key, then the map takes a snapshot of it when you perform the insert. That way, I can go and modify the key after the insert and any time thereafter if I look for the same sequence of integers, the map will find the associated value.

The problem here is that, in a language like Go, where pointer values are significant (contrast with Haskell, where two lists allocated separately but having the same contents are indistinguishable), you sometimes want to use pointer identity as the key so maybe it's hard to have it both ways.

Oh well. It's just something that surprises someone like me, who has grown accustomed to more value-oriented languages.


> Here's a trick that I expected to work but doesn't. Would be interested to hear the rationale if anyone knows it.

Per the spec[0]:

    The comparison operators == and != must be fully defined for operands 
    of the key type; thus the key type must not be a function, map, or 
    slice. If the key type is an interface type, these comparison 
    operators must be defined for the dynamic key values; failure will 
    cause a run-time panic.
[0] - https://golang.org/ref/spec#Map_types


By "rationale" I was thinking more along the lines of "here is the reason we chose to do it this way" not just "here is the way we chose to do it".


https://golang.org/doc/faq#map_keys

"Map lookup requires an equality operator, which slices do not implement. They don't implement equality because equality is not well defined on such types; there are multiple considerations involving shallow vs. deep comparison, pointer vs. value comparison, how to deal with recursive types, and so on. We may revisit this issue—and implementing equality for slices will not invalidate any existing programs—but without a clear idea of what equality of slices should mean, it was simpler to leave it out for now.

In Go 1, unlike prior releases, equality is defined for structs and arrays, so such types can be used as map keys. Slices still do not have a definition of equality, though."


Ah, perfect. Thank you.


I'm sure I'm not the only one, so could you explain the prank? Certainly the message you posted doesn't show up when I try to compile it...


I was thinking that some people would want to figure it out for themselves so I didn't want to spoil the challenge for them... I kind of hoped someone else would post the solution.

Anyway, here is a solution: http://play.golang.org/p/Mg8x7sJ-hR

In other words, just insert the following line:

    type int string
The thing is, "int" is not a reserved word in Go. It's just a predeclared binding. You can rebind it -- even use "int" as a local variable name, like so: http://play.golang.org/p/0_iTzkg-5m

There are other interesting cases. For example,

    var true = false // Perfectly valid Go code!
I think of it as a prank because you could sneak such a line into somebody's code and the compiler would not help them realize what had happened, it would just complain about a lot of nonsense like 1 not being an int. In the "var true = false" example, there would not even be a compiler error, you'd just get baffling runtime errors.

For a list of all the predeclared identifiers, see here: http://golang.org/ref/spec#Predeclared_identifiers



I thought this kind of magic code was explicitly what go creators didn't want.

If i compare to Objective-C "object respondsToSelector:selector()" or "object isKindOfClass" equivalent, this go "casting to an anonymous struct" code seems extremely convoluted.

Plus, i may be wrong, but it seems like it's really not robust. You're trying to cast to an anonymous struct declared locally, that isn't linked to any other interface anywhere, and only implements part of the methods defined in the File struct. It's looks to me just as robust as using strings. What you would like to express, is what's in the comment : aka, test against something related to the File struct/interface.


There are no anonymous structs in that slide, just anonymous interfaces.


Indeed, i think my point still hold though


Saw an earlier version of this talk @ the Berlin Go meetup earlier this week - the exploration and explanation of `sync/atomic` by Andrew is really great




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: