That said, a REPL would be nice. Seems like go compiles fast enough that some ambitious dork could make a REPL-faker?
Languages that have a REPL were engineered from the start to allow it. Go doesn't do late binding so much. It prioritized a higher degree of control over low level memory layout and substituted fast compiling for a REPL.
This is not because the tools are so bad we are forced to bang rocks together. It's because writing code is an effective way to diagnose bugs. Even when I'm in a full-blown IDE with a GUI debugger, I prefer to use printf debugging.
What makes it win is how easy it is to use. What makes it lose is how tedious and manual it is. And how it is restricted to an environment where you are allowed to recompile and load code all the time, and where the output is not going to mess up any other data stream.
I'm starting to phase out printf debugging in favor of tracing, because the tracing tools in Erlang are just infinitely better and more flexible, AND they can work on a production running system without impacting performance in any major way.
I'm able to match specific functions, with specific argument sets. I can see what they returned, and match only specific processes or generations of processes. I can do it from a REPL (because there is one, even in production systems, without needing to run stuff in a screen session), without messing up any related output stream.
Printf debugging is attractive because of how simple and minimally disruptive it is when you're already writing code. As much as it amazes me, it turned out not to be the most convenient tool available for most cases, even if I still use it from time to time.
However, let's say I'm given a third party library, and I know essentially what it does. I want to "see" the properties and methods of the object, I want to "inspect" values, and I want to "test" expressions, all at once. If you're just using printf, then between each of those steps you need to write a line of code, recompile, and reach that state in your program again. Like I said, if you already know essentially what's going on, deep dives like this become less and less important. However, I just think it's a boneheaded philosophy for a language / toolchain to just like...I don't know, assume you're good. I'm trying to become good, but I am getting more and more frustrated with Go every time the default answer to my problem is "be less of an idiot"
Sometimes, however, it's nice to be able to see a live flow of the program and to watch variables change as you step through. I think we'll see more powerful tooling for Go debugging coming through very soon.
I'd love to see more integration in the various editors for go oracle, go cover tool etc. as these would probably show me when I started introducing errors, with the relevant info a click (or key combo) away, before they turned into horrible bugs requiring their own git branch to solve. TDD with the go cover tool is brilliant!
Use cgdb for a nicer interface. Also, you can examine variables and set break points in gdb. Instead of a REPL, you can try out expressions in main(). Your workflow has to change, so if that's a deal-breaker, it is what it is. But if you can change, there are some advantages to be gained.
If the answer was, "yes, that would be great, we just haven't had the time for it", I would say awesome, and start working on building it. However, the general answer seems to be, "you are an idiot, get out of my language."
Well, asking for a REPL in Go is kind of like designing a bicycle for a fish. You can imagine what that would look like, but it's not really the most pragmatic or useful thing in context.
don't understand the need for a...debugger or any of these things, because they seem ultimately unconcerned about helping me or other newcomers out.
Are you sure that it's not partly that you haven't lurked around enough to come up to an acceptable level of background knowledge first? Maybe certain members of the Go community could've been more friendly, but one doesn't have to look very long to figure out that gdb is the standard way to debug Go. To be fair, such "background" is pretty easy to get wrong when going into unfamiliar territory. Sometimes, we don't even know what we yet need to learn. I've had such travails myself.
It's kind of ironic, since back in the day, I was a compiled language programmer who discovered dynamic languages like Perl then Smalltalk. Once I switched, I was frustrated by the too-broadly applied assumptions everyone had about programming in general. (Programming = edit-compile-test; "Where can I find the compiler?") Now, I find myself meeting dynamic language programmers who have no exposure to environments like C, where there is no managed VM and no dynamic runtime with even an inkling of late binding. We've somewhat come full circle.
There is even a C++ REPL somewhere. It basically compiles very time your enter the expression and runs the code. I think it can be done in Go (but someone correct me, if I am wrong here).
[1]: http://play.golang.org
For instance, there is very little in the toolchain about debugging other than "use GDB". For someone very familiar with the workflow of typing "debugger" in Javascript code, being able to stop the world at any state, examine variables, and having a fully-functional REPL to test expressions, Go's way of "debugging" code is...well. I don't really know how to do it in Go. The general answer seems to be something along the lines of "think about the code you wrote and then write it correctly you idiot."
Seriously, this is the canonical debugging advice, from Rob Pike himself:
"When something went wrong, I'd reflexively start to dig in to the problem, examining stack traces, sticking in print statements, invoking a debugger, and so on. But Ken would just stand and think, ignoring me and the code we'd just written. After a while I noticed a pattern: Ken would often understand the problem before I would, and would suddenly announce, "I know what's wrong." He was usually correct. I realized that Ken was building a mental model of the code and when something broke it was an error in the model. By thinking about how* that problem could happen, he'd intuit where the model was wrong or where our code must not be satisfying the model."*[1]
[1] http://www.informit.com/articles/article.aspx?p=1941206