Leveraging the Go Type System
91–100 of 112 posts
Re: Leveraging the Go Type System
#92I am once again underwhelmed by the amazing might of a type system.
I hope you mean Golang's type system. It is indeed underwhelming. However it is arguably the poorest type system in popular usage. Therr exists much better, which I encourage you to explore - Typescript, Haskell, Rust
Re: Leveraging the Go Type System
#93We have a useful lower bound for type-system richness: if you're developing a new language in the 21st century and your type system is not at least as rich as Hindley-Milner, do not expect programmers to take your language seriously.
Re: Leveraging the Go Type System
#94Earlier quoted context omitted.
> To be fair, Go's package management is far from sane (though better than nothing, of course) It's not perfect, but it's among the best. It's far better than the popular offerings for Python, C, C++, and Java. NPM was also pretty terrible last I used it (needed to regularly blow away node_modules and reinstall things, random ENOENT errors, etc) and I think the .net world almost adopted a sane project file structure…
Makes sense, after all it is catching up with Mac OS, OS/2 and Windows 95 IDEs.
Re: Leveraging the Go Type System
#95Earlier quoted context omitted.
That boiler plate usually can be generated for you. See Go's stringer which does all the magic for you. All you have to do is define the type and constants, and a go generate directive.
would you have a sample code? sounds interesting
// pill.go
package painkiller
//go:generate stringer -type=Pill
type Pill int
const (
Placebo Pill = iota
Aspirin
Ibuprofen
Paracetamol
Acetaminophen = Paracetamol
)
Then running `go generate` will yield: $ cat pill_string.go
// Code generated by "stringer -type=Pill"; DO NOT EDIT.
package painkiller
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Placebo-0]
_ = x[Aspirin-1]
_ = x[Ibuprofen-2]
_ = x[Paracetamol-3]
}
const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"
var _Pill_index = [...]uint8{0, 7, 14, 23, 34}
func (i Pill) String() string {
if i = Pill(len(_Pill_index)-1) {
return "Pill(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]
}
Note: indentation is messing up because of Hacker News, so ignore the indentation.Re: Leveraging the Go Type System
#96Earlier quoted context omitted.
Makes sense, after all it is catching up with Mac OS, OS/2 and Windows 95 IDEs.
Yeah, I imagine it's a real problem for the people who don't know their way around a shell.
Re: Leveraging the Go Type System
#97Earlier quoted context omitted.
That boiler plate usually can be generated for you. See Go's stringer which does all the magic for you. All you have to do is define the type and constants, and a go generate directive.
And install stringer in every dev env, and debug all the boilerplate anyway when things go wrong. Code generation is always the last resort.
Where I work we are a go house, and the number of tools I've seen in our pre-commit configurations and in our development environment setup scripts is pretty intense. So is the number of questions around said tooling. There's a lot more friction than I'd expect. I can't even use lack of experience as an excuse for these questions because they're really talented people. Some of them have worked on the product for years, and have literally moulded the product's tooling into what it is today.
Re: Leveraging the Go Type System
#98Earlier quoted context omitted.
Go has many shortcomings that make it difficult and extremely annoying to do refactorings. Things like no constructors where types are declared as follows A { Field1: field1, Field2, field2, } Now adding a new field to A would require ensuring that all code paths initialize Field3, otherwise you're going to have silent errors at runtime. This has been solved ages ago in Java and C# and similar languages by means of c…
A constructor is just a function though... If I add a new field to a Java class and fail to add its initialization to the constructor, I have the exact same problem because Java initializes the field to its default value when the constructor is called. You are correct that every situation where the struct in Go is initialized "bare" would need to be addressed if a field is added, but Go considers this a feature, not…
I see this dismissive philosophy in golang a lot (I'm not saying you're doing it, mind you). The entire language is full of arbitrariness. I've seen enums being dismissed by the golang team just because, without providing any meaningful arguments. Same with how nullability was not addressed in the language, contrary to how proper modern languages have tacked the issue. The excuse? "that's how the underlying machine operates". Quite meaningless and dismissive really.
Time and time again, it's been shown that the goal is to have a simplistic (not simple) language that also makes it easy to write the compiler for. This breaks down at larger scales because reality is complicated.
Re: Leveraging the Go Type System
#99Earlier quoted context omitted.
To be fair, Go's package management is far from sane (though better than nothing, of course). The tooling is also sub-par for modern languages, especially in terms of free development environments, though go-pls is slowly improving.
> To be fair, Go's package management is far from sane (though better than nothing, of course) It's not perfect, but it's among the best. It's far better than the popular offerings for Python, C, C++, and Java. NPM was also pretty terrible last I used it (needed to regularly blow away node_modules and reinstall things, random ENOENT errors, etc) and I think the .net world almost adopted a sane project file structure…
Maven is significantly better than Go modules: it doesn't require special support from your git server, it doesn't rely on magic tags with magic formats, it does strict dependencies by default, it handles branching any way you want, it works with binary artifacts not just source code, it has explicit support for custom repos, it doesn't require renaming your package to do a major version upgrade, it doesn't rely on DNS for package names, it works for small cross-language dependencies, and probably others.
> For other things though, Go is great. Testing? Built in. Benchmarking? Built in. Profiling? Built in. Cross compilation? Built in. Static linkage? It's the default. Formatting? Built in. Documentation generation? Built in. Code and documentation packaging and publishing? Built in (to git).
Testing is actually pretty bad, go test is OK, but the lack of any kind of basic testing tools like a deep equality or mocking helpers make it much harder to use than most. Code coverage measurement is also pretty bad, and un configurable.
Benchmarking is decent, it's nice to have it built in, no complaints there.
Profiling is horrible, just some text format that's barely documented, no memory dumps, no thread bases profiling, no tooling to analyze complex profiles.
Cross compilation is nice, but it's not even required in the most direct competitors (Java, C#).
Static linkage is the only option, and neither a good nor a bad feature.
Formatting is forced on everyone, and is completely unconfigurable. Their choices often mess up for merges for stupid anesthetic reasons.
Documentation is built-in to Java and C# as well, and it supports more than basic text for describing your code. They also don't rely in any way on your choice of source control system.
Overall, Go's ecosystem is definitely sub par compared to Java or C#. It's not the worse, and it can do the job, but you'll never be as productive.
Their support for small fats starting binaries is the only thing where Go really shines.
Re: Leveraging the Go Type System
#100Earlier quoted context omitted.
Think about the use case of a library import. In golang, the user has the ability to change library "constants", wreaking havoc in the process. Secondly, `final` serves as strong and clear documentation. We know just from looking at the definition that this is variable is not going to be re-bound. On a side note, this compiles in golang: func main() { true := false if !true { fmt.Println("wat") } }
I mean, at some point, garbage in garbage out, no? For example, in javascript, you can do `Array.prototype.map = null`, in C you can do `#define if while`, etc. It's highly unidiomatic to mutate bindings from libraries in any language, even ones that technically allow you to, so the observation that go is one of those languages feels like nitpicking at obscurities. My Java is rusty, but I recall that several years ag…
Yes, but a good language is supposed to minimize chances of error, especially one that was designed after C, C++, and Java. The industry progressed, and we have a better understanding of what some good ideas are, and which to avoid. The fact that golang allows null pointers is inexcusable IMO. C# was able to retrofit a nullable handling mechanism into the language, and practically any useful language that was designed after that had some sort of nullable type handling (Scala, Kotlin, Rust, and I believe Zig and Nim as well, etc.).