9 comments

  • kubb 616 days ago
    It's always important to ask yourself what concepts you knew before you learned a new technology X. For someone who knows C++ and Java there are no new concepts in Go, so the tour of Go should suffice.

    For someone who doesn't know what a function, a pointer, and a string is, there's more work to be done.

    One of the reasons Go is praised for simplicity is that it only requires us to know basic concepts. You already know how to call a function and store some integers in a struct. All you need is to get used to the new syntax.

    For those who like to flex their brains and learn to think in new ways, this could be a disadvantage, but for someone overwhelmed with information it's a godsend.

    On the other hand, if you always limit yourself to Go then it will be harder to pick up other technologies that take advantage of concepts not featured there.

    • thejammahimself 616 days ago
      I feel like a significant part of learning a new language is also learning the standard library alongside the new syntax. Especially because these can be quite different between different languages.
      • Groxx 616 days ago
        Yeah. Particularly after having learned 2 or 3 languages, learning the N+1th language is often the work of like an hour or three.

        Learning the standard library, and the patterns it has encouraged in the community, takes years and is a moving target. Even a basic (accurate) "feel" for things generally takes weeks, regardless of how "simple" the language is. You might be able to produce code prior to that, but being able to predict where something should be, or how to find it, takes time.

      • nerdponx 616 days ago
        Not just the standard library, but also its idioms and the tools that people commonly use to work with the language (compiler, build tool, etc).
      • mxuribe 616 days ago
        > I feel like a significant part of learning a new language is also learning the standard library alongside the new syntax...

        OMG, you are so right! I feel the same. Knowing what the standard libraries bring (or don't bring) for each language that one learsn is immensely helpful. Sometimes this helps me decide which language to use for particular use-case/project, or sometimes it helps me better understand what the level of effort will be for a project if i use langugae X vs language Y, and on and on, etc. I feel like a tour of each language's standard libraries is a must when learning a new language; or at least a cusrosry review of the most important and/.or most often used functions, etc. of said standard libs.

      • kubb 616 days ago
        What do you think about rosetta code, et al? For me they reduce the standard library issue quite a bit, combined with googling "how to do x in y".
    • eweise 616 days ago
      Trying to find something I agree with in this post. I programmed in Java for decades and found that there were plenty of new concepts to learn in Go. Not sure asking myself what concepts I knew would help me in learning Go, especially since I know the concepts, I don't need to ask myself whether I know them. Some concepts not in Java

      - Pointers. These take a while to understand and use effectively. https://www.timr.co/go-interfaces-the-tricky-parts

      - Error handling. Very different than exceptions

      - Interfaces. Not quite the same as Java's and used differently in some cases

      - Channels. Java doesn't have these

      - Context. passing these around everywhere instead of just sticking on a threadlocal.

      Go will flex your brain plenty since you have to unlearn what you thought were good programming practices such as only one return statement per method.

    • eikenberry 616 days ago
      > [..] there are no new concepts in Go [..]

      Except for native support for CSP and that programs should be written in a CSP style. Learning Go and skipping CSP is not learning Go.

      • morelisp 616 days ago
        > Learning Go and skipping CSP is not learning Go.

        Learning Go seems to be inevitably "learning CSP", using way too much "CSP", then eventually coming to your senses and going back to atomic types and locks for probably 70% of cases.

        • eikenberry 616 days ago
          Thinking CSP is something you can replace with atomic types and locks is a common misconception. Goroutines and channels are the primitives used by CSP, but just using them is not CSP. CSP is a whole program design system that can use all the concurrency primitives. There is no conflict between the using CSP and locks/atomic types. They work well together as they have different uses.

          The misconception is pretty widespread and cancerous to the community. Ignoring CSP is ignoring Go's best feature for writing better code. It takes some time to learn to do well (I'm still working on it) as it is a different paradigm than most people are used to, but it is well worth the effort IMO.

    • Xeoncross 616 days ago
      While I agree there aren't really any new concepts, I can think of two areas in Go that C++ and Java don't really prepare you for: error handling / nesting and classes. Go doesn't use exceptions or classes for anything really. Instead it's all DI/object embedding + interfaces and nested error values + context which can be more of a mind hurdle than expected since inheritance and try/catch are so common these days.
      • skrtskrt 616 days ago
        Go channels are one that's pretty new depending on the language. I came from Python using async for all concurrency, so channels are an odd concept.

        Passing context around is an interesting one too

        • kubb 616 days ago
          yes, channels and goroutines are a concept that doesn't transfer from C++ or Java :) good job pointing out the exception!
          • fnord123 616 days ago
            > good job pointing out the exception!

            No, go doesn't have exceptions. :D

            To answer the sibling comment (I don't have enough karma to go deeper), Java NIO channels are barely usable. Using them is the quickest way to inject bugs into your code I've seen in Java.

            Go channels are closer to blocking queues or a selection of concurrent queues depending on whether it's bounded or unbounded, or whether you use select, etc.

            • kubb 616 days ago
              it has panic/recover though which is like exceptions :)
          • 62951413 616 days ago
            I believe idioms for dealing with golang channels resemble NIO channels/selectors (e.g. https://docs.oracle.com/javase/8/docs/api/java/nio/channels/...). JDK1.4 was already widely used around 2005 ;)
            • morelisp 616 days ago
              The idioms for Go channels as well as NIO channels resemble those of any asynchronous file descriptor handling. Long predating 2005. (And more to the point, still relatively uncommon outside actual I/O in Java.)
      • 62951413 616 days ago
        I cannot help thinking that golang's error handling is isomorphic to

        * returning an error code from functions in C and all the time writing "err = f(); if (err != 0) .."

        * returning a potentially null reference from a method in Java and all the time writing "var ref = f(); if (ref != null) .."

        Exceptions were supposed to save us from this drudgery in late 90s. They did if you ask me. Options are a nice alternative if FP is your cup of tea.

      • latchkey 616 days ago
        As an old Java head, I found FX [1] to fill a missing DI gap for me. Some can argue that it isn't really needed in go, and I tend to agree, but after using it in a few large projects, I find that it encourages a good separation of concerns that enables things to be easier tested as well as prevents cyclical imports.

        [1] https://github.com/uber-go/fx

        • arwineap 616 days ago
          I've found that fx is very popular with java devs

          Can you help me understand what this style of dependency injection solves for in java?

          I use packages to encourage separation of concerns

          • latchkey 616 days ago
            If you start to write pkg.NewFoo() inside of functions, you get into a whole object dependency mess that makes testing really really difficult. Having something that encourages you to pass in constructed objects (ala: DI), in the constructor, it ends up being much easier because you can more easily mock objects as necessary. Obviously, you can use that same pattern on your own without fx, but going all in on fx really kind of forces you to do it.

            Bonus fx points for being able to start/stop services as well. However, this tends to factor more into single binary apps (which is what I've built), more than say restful web endpoints (also built, but don't use this feature of fx as much).

            • randomdata 616 days ago
              > Obviously, you can use that same pattern on your own without fx, but going all in on fx really kind of forces you to do it.

              Unless you are trying to add tests to legacy code, where you also wouldn't have much say in the use of fx, wouldn't the stated testing difficultly already force you away from that dependency mess?

              • latchkey 616 days ago
                I've found that unless I write code in golang in a way that was intentionally written to be unit tested, it is very hard to bolt on unit testing after the fact. I'm stuck with effectively just integration testing. I don't envy you working on legacy code.

                  struct Foo {
                  }
                
                  func (f *Foo) doSomething() {
                     client := pkg.NewClient()
                     client.doHttpRequest()
                  }
                
                vs.

                  struct Foo {
                    client Client
                  }
                
                  func (f *Foo) doSomething() {
                     f.client.doHttpRequest()
                  }
                
                  func NewFoo(client Client) *Foo {
                    return &Foo{ client: client }
                  }
                
                  var FooModule = fx.Provide(NewFoo)
                
                then to use it...

                  struct Bar {
                    foo *Foo
                  }
                
                  func NewBar(foo *Foo) *Bar {
                    return &Bar{foo: foo}
                  }
                
                  var BarModule = fx.Provide(NewBar)
                
                how do you unit test the first example? There is no easy way to that without having the client do things special internally, which leads to a rats nest of issues and doesn't scale. Easier to just pass in a mock client and make sure the right http request/responses are being done.

                fx kind of highly encourages the second approach for all of your code. It is a bit more boilerplate, but by default, I'm always going to be thinking about passing my dependencies around instead of just being lazy and doing NewClient in the function.

                I also get to take advantage of the fact that Client is just magically passed into my constructor. If there is some error doing so (like I forget to Provide), then fx will give me errors at start up. My dependency chain is clear. It just feels nicer to me.

                Once again, of course I can write it the second way without fx... but it is kind of nice that every time I want to use Foo, I don't have to type NewFoo() in a constructor... I just reference *Foo.

                By the way, mockery [1] generates super easy to use mocks for exactly this workflow.

                [1] https://github.com/vektra/mockery

                • randomdata 616 days ago
                  > I've found that unless I write code in golang in a way that was intentionally written to be unit tested, it is very hard to bolt on unit testing after the fact.

                  Absolutely. This is true in most, if not all, languages. But when you're in the driver's seat, able to make choices like whether or not to use fx, why would you bolt on testing after the fact?

                  Not much you can do about legacy code, if that's what you have to deal with, but when dealing with legacy code it is unlikely the authors used fx, so...

                  • latchkey 616 days ago
                    As you refactor the code to be more testable, you can add in fx. It doesn't have to be from the beginning.
                    • randomdata 616 days ago
                      If you refactor code to be more testable then it is testing that is forcing you, not fx.
                      • latchkey 616 days ago
                        Correct, I haven't argued any differently. You introduce fx in, start writing tests and it will convince the other developers you're working with that there is importance to how you build the codebase in such a way as to enable testing.
                        • randomdata 616 days ago
                          Then you must have mistakenly replied to the wrong thread? If you are in a position where you can introduce fx, then you are also in a position to introduce testing, and testing will already force testable code. If fx can help your code, great, but that's orthogonal to the discussion.
      • kubb 616 days ago
        you're right, fortunately stopping to use a concept is easier than learning a new one
    • tylerhou 616 days ago
      A big new concept in Go is that methods can have value receivers or pointer receivers. In C++ and Java, there is no distinction. Plus, method calls automatically deref pointers.

      I think it took me a day to realize this when my code wasn't compiling.

      That, and goroutines + channels (especially blocking behavior).

    • ryanschneider 616 days ago
      The first time I returned the address of a local variable from a function and it _wasn’t_ a footgun was eye opening. Then digging into why that actually worked and understanding how go does escape analysis gave me more respect for the language and it’s compiler.
    • pram 616 days ago
      The hard part about learning new languages for me is purging all the old information I have. For example, Perl sigils messed me up for a long time because other languages don't prefix variables and stuff with a symbol. It felt so wrong!
      • rad_gruchalski 616 days ago
        PHP does. Not the the extent of Perl, but it does.
        • Keyframe 616 days ago
          MEL does as well. Tcl too (sometimes).
    • icemanx 616 days ago
      So a Java and C++ Developer will know what a TEE channel is?
  • Xeoncross 616 days ago
    I wish more people encouraged people new to Go to look at some of the targets you'll arrive at so that people don't come into Go thinking the end result is going to be using the Go version of Laravel, Spring, or Rails.

    Go has some interesting ideas about models/ORM's, OpenAPI, validation, templates, embedded binary files and other things. When types matter, like in Go, code generation is often very important as well which isn't as common in scripting languages.

    https://goa.design/ for grpc/rest servers based on specs

    https://gokit.io/ for microservices

    https://github.com/mustafaakin/gongular demonstrates object-based validation using struct tags

    https://sqlc.dev/ for generated models based on SQL (skip the whole idea of an ORM)

    https://github.com/jmoiron/sqlx for more traditional object population from SQL

    https://pkg.go.dev/errors for an understanding of wrapping errors and nested error causes

    https://gqlgen.com/ for auto-generated revolvers based on GraphQL schemas

    https://pkg.go.dev/io#Reader all the Reader/Writer/Closer's as they are everywhere since Go cares about performance and therefore streaming abilities. No more string passing.

    As mentioned in the article, flags matter in Go. The most popular https://cobra.dev/ and the simpler https://pkg.go.dev/github.com/peterbourgon/ff/v3/ffcli provide some good examples

    This comment is mostly for web apps, different domains will require looking at all the approaches taken in https://github.com/avelino/awesome-go by leading packages

    • morelisp 616 days ago
      > When types matter... https://github.com/mustafaakin/gongular demonstrates object-based validation using struct tags

      Yikes.

      When types matter, you make a newtype and use UnmarshalText!

      • Xeoncross 616 days ago
        Yeah, that's another good approach but not the most beginner friendly.

        A large portion of the Go community uses/abuses struct tags so knowing about them and seeing a system designed around them is important even if you won't use gongular because you're using ent or goa.

        echo, buffalo, gin, etc... all use object struct tags for input data binding and there are two large validation packages that focus on this use.

        • morelisp 616 days ago
          My point is, "struct tags for validation", despite being depressingly common, is definitely something more for "the Go version of Laravel, Spring, or Rails." I would not highlight anything built that way for developers looking for Go's interesting ideas.
  • eatonphil 616 days ago
    I'm working on a collection of small but meaningful programs for learning a new language. tinyprograms.org (or github.com/eatonphil/tinyprograms).

    I don't have many yet, just 3 (if you have ideas, lemme know). But porting them has already helped me start learning Zig and FreePascal; two languages I've been meaning to learn for a while.

  • swozey 616 days ago
    I'm waiting on Designing Data Intensive apps to get delivered. Not sure if it covers this:

    Is there a good book for people without a compsci background to better understand terms?

    I've been learning Rust (and lots of go) as my first language and the terminology of things really throws me off, I feel like simple concepts are wrapped around what sound like confusing math words/phrasing.

    I'm partially trying to learn syntax, language'isms and vocabulary at the same time.

    • jamal-kumar 616 days ago
      Rust is a really weird language to pick up as your first for all of the reasons you're explaining, it's full of a ton of concepts and terminology which come from design patterns and assumption of knowledge that was determined in other languages before it for building complex software effectively. You will probably enjoy the rust documentation glossary, [1] and the golang reference specification while super dry is a good thing to go over once or twice as well [2]

      All the power to you to get through challenge mode. My first languages were C and javascript when the documentation was pretty much just books, but the amount of resources online these days is just incredible. After you learn a couple of them the rest get a lot easier. If you're stuck on math-related computer stuff I liked the Schaum's outline of essential computer mathematics a lot for getting up to speed. [3]

      If you're looking to make things a little bit easier you could aim for higher level languages which don't require you to think as hard about what you mentioned because it's abstracted away. Python is popular for this reason and has a ton of immediate practical use, but I also like Ruby and Lua for ease of writing. Just keep in mind that these languages tend to get comparatively harder to use the larger or tighter your program's requirements get.

      [1] https://doc.rust-lang.org/reference/glossary.html

      [2] https://go.dev/ref/spec

      [3] https://www.abebooks.com/9780070379909/Schaums-Outline-Essen...

    • zumu 615 days ago
      > Is there a good book for people without a compsci background to better understand terms?

      This isn't going to solve your immediate problem, but the trick is to build your own compsci background. Data Structures, Algo, Operating Systems, Discrete Math, etc. courses are all available online various platforms (youtube has a lot of the lectures). I went through lectures and problems from Cornell, Stanford, CMU and MIT online for free. It is gonna take some time, but I suggest starting to chip away at the lectures. It's a nice break from actively hacking on something.

    • mecsred 616 days ago
      I also don't have a compsci background, but wanted to develop my programming skills at work. The book "The Pragmatic Programmer" was recommended to me, and I feel like it made a big impact on my code quality. Particularly when programming with a team. It covers higher level concepts and organization in code.
    • asadawadia 616 days ago
      >understand terms?

      What do you mean understand terms?

      If you need help with programming check out the link in my profile and we can set some time up - it will be more beneficial than buying a book

      • nindalf 616 days ago
        Please don't self promote your consulting business. A person starting out their learning journey definitely does not need to hire a consultant. This is exceedingly predatory.
        • eatonphil 616 days ago
          HN (well, @dang anyway) doesn't have a problem with self-promotion [0], especially when it's in context and not excessive. GPs offer seems in context.

          [0] https://news.ycombinator.com/item?id=17335050

          • nindalf 616 days ago
            You think a person writing hello world needs to hire a consultant at hourly rates?
        • asadawadia 616 days ago
          Mentoring and helping is not predatory
  • xavdid 611 days ago
    I've been picking this up for work while reading "The Go Programming Language" (https://www.gopl.io/). I like using a book over picking small projects and repeatedly googling things because the book gives a lot of context. I know _how_ all the pieces fit together and am given credible recommendations on what to use and why. It's a slow way to learn "how to use X data structure", but a great way to know "how X data structure works under the hood and why/when that's important".

    The language itself is neat. Obviously very fast. Ergonomically sort of clunky (as compared to other languages, like TS or Python), but I think that'll smooth over with time. It also makes "hard things" in other languages simple, especially its threading and inter-thread communication.

  • sremani 616 days ago
    I heartily recommend this book, on this subject.

    https://www.amazon.com/Programmers-Brain-every-programmer-co...

  • purpleblue 616 days ago
    I've worked with a dozen different languages across a dozen different environments during my career. The languages I will never work with again, and would rather quit than use them again are:

    perl: This is the worst language I've come across. There are multiple different ways to do the exact same thing, sometimes the rules are understandable but mostly they are insane. For example, the "or" vs "||" is ridiculous to me, and the different namespaces between scalars and vectors such that you can have $a[$a] if I remember correctly. To me, it's a mess of hacks and 'this sounds like a great idea' that makes it almost impossible to maintain over long term.

    ruby: In my opinion, ruby suffers the same fundamental problem as php, which is that designers learn to use it instead of those with CS backgrounds, and produce terrible code and terrible practices. I developed on php for a few years, and the company had a hard time finding new employees that would meet the hiring bar because everyone that applied didn't have a CS background so the entire company pivoted to Java. With ruby, you also have inexplicable shortcuts that make code very hard to read, like no distinction between member functions and member variables, things being optional or not like ?, etc. Reading ruby was extremely hard to me, and if you have a large codebase, it's torture.

    scala: I know scala is revered by many but I hated it, but admittedly I only used it for a few brief and painful months. It's the first coding language I used that I couldn't survive without an IDE to help me figure out where code was coming from. It was basically impossible to trace through code without an IDE, at least for me. I think it does the same thing that perl does, which is give multiple ways to do the same thing which makes it very hard to read, and the "you don't have to do this if you want" mentality which also makes it hard to read especially for noobs. I hated it.

    In my opinion, the easiest language to work in is go. Go has an opinionated, single way to do things, and go fmt is the ultimate arbiter or coding style. No more arguments! I LOVE that you have no choice because it means you have less cognitive load to worry about. Yes, you lose creativity but at the benefit of maintainability. It's not my favorite language, but in terms of how easy it is to jump into a codebase, I feel that it's go. The only thing that I don't like is that package names and struct names are hard to differentiate, so you need the IDE to sort that out for you. For example tool.func1() could either being an package or a struct, so this needs IDE help as well.

    My favorite language is Python. I can do things in Python in 5-10 mins that would take me 1 hour in C++ to do in boiler plate. To me, it's the most productive language if you want to get stuff done as quickly as possible. It doesn't scale like compiled languages, but that's a problem for success and most don't reach that stage in the first place.

  • vaporup 616 days ago
    Are there now any libraries which can parse dynamic YAML files?

    I found it very hard to do with map[string]interface{} or figuring out which kind of structs to create...

    For JSON there seem to be many libs now which can do this.

  • unixhero 616 days ago
    Derek Banas published a fresh complete walkthrough of Go only 5 days ago.

    https://youtu.be/YzLrWHZa-Kc

    • hbn 616 days ago
      I've skimmed through some of his videos in the past to get a basic introduction to syntax and core concepts, but I can't help but think they're not very useful for much more than that. I'm not really sure what skill level his videos are targeting. He spends a long time on basic stuff like if statements - like do you really need to watch a guy type the classic age check if-else-if-else example for 3 minutes when anyone with basic programming experience could get the same information from just being shown a blurb of text doing an if statement? But then the more interesting stuff like goroutines and concurrency get about the same amount of time as if statements before moving onto something else. I feel like it doesn't really activate my brain at all.

      And especially for a language like Golang where there's a pretty good, comprehensive, official interactive tour[1], I don't know why you'd watch a guy type for 4 hours.

      https://go.dev/tour/welcome/1

      • unixhero 616 days ago
        I for one wildly apprechiate his content and language walkthroughs. I am an economist, and not a trained programmer so I don't have a strong intuition as a software engineer a has.