Disadvantage of Go

1,036 views
Skip to first unread message

hui zhang

unread,
Jan 13, 2017, 2:44:10 AM1/13/17
to golang-nuts
Disadvantage of Go
1  No Generic For Now
That make user coding repeat code many times, even for basic type such as int float bool
It is not easy , even to make a generic min function.
using interface will always check type casting.
and for []interface{} in generic function, u can't do cast

2   Incomplete  Type  in Basic Lib
Take math lib as an example,   math.Max math.Min are only for float64 , 
you have do stupid conversion for other type.

3  No Default Value for struct.
Consider multilayer struct.   A {B {C {D {E {F} } } } 
to init A to a default value will be complicated.
And how about  A[] slice
And what if D E F are from third party lib ?  
You have to dig into 3rd party code just for its default value. 
For It may have none zero default value.

4 Can not Cycle import.
package A B can not import each other at the same time. 
While other language can.
It seems not a big deal just put the the common thing in a new package
But when the package and project grow bigger, it just easy to say.
This change will affect all caller.

5  Inconsistent type conversion 
bool type are normal type just like int and float , 
but u can't do below.  while other type can cast to others
int(bool) bool(int) 


6  No multi casting expression
func foo() (int16, int8)    
var i,j int32 = (int32,int32)(foo())
Since go can't do this, why go provide multi return value.

7 No Ternary Expression
hardly find a language without it except go

8 No Negative Index for slice 
all other script language support a[-1] as a[len(a)-1]


When programing in go 
we have to do repeated type casting many times, due to the above.
write long code for Ternary ,int(bool) a[-1] etc
init big struct with default value.
Which make Go not an Elegant and simple language.
Once I thought go was a simple language, 
but in fact we write more code.

All above are proposal for many times. 
And it is 6 years(or more).
These basic functions are still not added. some of that should be add in version 1.0
I belive most above could make go simpler, 
someone know  a little programing could know how to use it.
however someone still fear it make go complicate like c++ 

Shawn Milochik

unread,
Jan 13, 2017, 2:53:04 AM1/13/17
to golang-nuts
I recommend reading this. It addresses several of your concerns.


No decisions were made to annoy developers. Different people coming from different languages see different things as "flaws," when in reality they are just differences.

Also:


Enjoy the article! It's very informative and will give you a lot of insight into a lot of decisions that were intentional decisions -- not accidents.


Egon

unread,
Jan 13, 2017, 3:39:55 AM1/13/17
to golang-nuts
As Shawn mentioned, most of these were decided against for varying reasons. I'll try to give as much info as I can remember.

On Friday, 13 January 2017 09:44:10 UTC+2, hui zhang wrote:
Disadvantage of Go
1  No Generic For Now
That make user coding repeat code many times, even for basic type such as int float bool
It is not easy , even to make a generic min function. 
using interface will always check type casting.
and for []interface{} in generic function, u can't do cast 

You cannot cast []interface{} to []float64 because they have different memory layouts.
 

2   Incomplete  Type  in Basic Lib
Take math lib as an example,   math.Max math.Min are only for float64 , 
you have do stupid conversion for other type. 

3  No Default Value for struct.
Consider multilayer struct.   A {B {C {D {E {F} } } } 
to init A to a default value will be complicated.
And how about  A[] slice
And what if D E F are from third party lib ?  
You have to dig into 3rd party code just for its default value. 
For It may have none zero default value. 

All structs are zero initialized.

If you had default-values for structs the overhead of constructing something becomes non-obvious.
 

4 Can not Cycle import.
package A B can not import each other at the same time. 
While other language can.
It seems not a big deal just put the the common thing in a new package
But when the package and project grow bigger, it just easy to say.
This change will affect all caller.

Structures that have cyclic dependencies have longer compile times, init order becomes more confusing and prone for errors, and a program having cyclic imports is harder to understand than one without it (usually).

Break cycles with DI.


5  Inconsistent type conversion 
bool type are normal type just like int and float , 
but u can't do below.  while other type can cast to others
int(bool) bool(int) 


 
6  No multi casting expression
func foo() (int16, int8)    
var i,j int32 = (int32,int32)(foo())
Since go can't do this, why go provide multi return value.

Why would you not return int32 immediately from `foo`?
Why would you write `foo` in the first place?

7 No Ternary Expression
hardly find a language without it except go 

8 No Negative Index for slice 
all other script language support a[-1] as a[len(a)-1]

In such situations, indexing that involves computation (e.g. `a[n-5]`) can easily hide mistakes.
 

When programing in go 
we have to do repeated type casting many times, due to the above.
write long code for Ternary ,int(bool) a[-1] etc

If you repeatedly need to use it, then:

func ifthen(v bool, a, b int) { if v { return a; }; return b }
func asint(v bool) int { return ifthen(v, 1, 0) }

x := ifthen(a < b, a, b)

init big struct with default value.
Which make Go not an Elegant and simple language.
Once I thought go was a simple language, 
but in fact we write more code.

All above are proposal for many times. 
And it is 6 years(or more).
These basic functions are still not added. some of that should be add in version 1.0
I belive most above could make go simpler, 
someone know  a little programing could know how to use it.
however someone still fear it make go complicate like c++ 

But, it seems to me you are trying to use Go as a language that it is not. Can you show the code where you are having problems with some/all of these points, then we can discuss how to avoid these situations in the first place.

If you try to use any language in a way that it was meant to, you will have problems.

+ Egon

Egon

unread,
Jan 13, 2017, 3:44:59 AM1/13/17
to golang-nuts
I also forgot to mention that Go is not "perfect" for everything and it tries not to be.

Sometimes the correct answer is some other language (e.g. Matlab, R, Julia, C, Rust, Chapel, Haskell, Prolog, Erlang... and, many, many more)

+ Egon

hui zhang

unread,
Jan 13, 2017, 4:26:29 AM1/13/17
to golang-nuts
thank u very much.  I know they all have work around.  and I also write some util my own.
I just wish go to make it more simpler, wish the code could be clean and short . 
Right now go let programer do repeat and Mechanical work

the top 3  are bothering me most
[1],[2] let me do many type cast all the time.
[3]      let me have to do initialize default for each struct.
right now I am solving [3] like this.
type F struct {x int32}
var FDefault = F{x:1}
type E struct {f F}
var EDefault = E{f: FDefault}
type D struct {e E}
var DDefault = D{e: EDefault}



在 2017年1月13日星期五 UTC+8下午4:39:55,Egon写道:

Egon

unread,
Jan 13, 2017, 4:49:46 AM1/13/17
to golang-nuts


On Friday, 13 January 2017 11:26:29 UTC+2, hui zhang wrote:
thank u very much.  I know they all have work around.  and I also write some util my own.
I just wish go to make it more simpler, wish the code could be clean and short . 
Right now go let programer do repeat and Mechanical work

the top 3  are bothering me most
[1],[2] let me do many type cast all the time.
[3]      let me have to do initialize default for each struct.
right now I am solving [3] like this.
type F struct {x int32}
var FDefault = F{x:1}
type E struct {f F}
var EDefault = E{f: FDefault}
type D struct {e E}
var DDefault = D{e: EDefault}


What is the actual code that you are working on? I doubt you have structs named F, E, D.

It's very hard to suggest a better model for "something" without knowing what that "something" is.

+ Egon

roger peppe

unread,
Jan 13, 2017, 4:56:48 AM1/13/17
to hui zhang, golang-nuts
On 13 January 2017 at 07:44, hui zhang <fastf...@gmail.com> wrote:
> 4 Can not Cycle import.

In my opinion, this is one of Go's really great features. When software becomes
larger, there is huge pressure to create cyclic dependencies between packages.
Once you start to get cyclic dependencies, the system as a whole tends
inevitably
to gather into a giant "ball of mud". That makes everything less
modular and much
harder to refactor.

There are so many times that I would have created a cyclic dependency rather
than spending a day or two teasing out the dependencies into something
non-cyclic.
This process almost always creates something better engineered than before
with a better separation of concerns.

Also, as Egon says, there's a good technical reason: the Go
initialisation order depends
fundamentally on non-cyclic imports - there's no way to see an
imported package's initialised
global variables in an uninitialised state.

Egon

unread,
Jan 13, 2017, 5:00:41 AM1/13/17
to golang-nuts, fastf...@gmail.com
There's a way, but it's not pretty (Delphi can have these issues with initialization order and it's a pain to fix/debug in a big project.)

hui zhang

unread,
Jan 13, 2017, 9:39:30 AM1/13/17
to golang-nuts
I just list A B C D E F  as  an example.
In real project we will use struct in struct .
when the struct goes deeper, and it may be managed by other people,
 if the deepest struct need a default value. F{x:1} 
The upper struct user "must" known the detail. 
here below I just figure out a way below to do that, but it's not a common way, just I know it .
 Other people who use my lib may not .  So he maybe use the zero value F{}  not F{x:1}
type F struct {x int32}
var FDefault = F{x:1}
type E struct {f F}
var EDefault = E{f: FDefault}
type D struct {e E}
var DDefault = D{e: EDefault}

在 2017年1月13日星期五 UTC+8下午5:49:46,Egon写道:

Michael Jones

unread,
Jan 13, 2017, 9:41:54 AM1/13/17
to Egon, golang-nuts, fastf...@gmail.com
One minor point is that you cannot fake the ternary operator with a function. In the function call the two alternates are evaluated before the call so this breaks

I = (k==3) ? a++ : b++

and everything  else with side effects such as function calls. 

--


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.


For more options, visit https://groups.google.com/d/optout.


hui zhang

unread,
Jan 13, 2017, 9:47:57 AM1/13/17
to golang-nuts, fastf...@gmail.com
Yes ,   cycle import is a bad design.
But as the software becomes larger , not everything is controllable.
In real project , some times it is a great risk to do refactor.

在 2017年1月13日星期五 UTC+8下午5:56:48,rog写道:

Axel Wagner

unread,
Jan 13, 2017, 9:57:56 AM1/13/17
to hui zhang, golang-nuts
If your struct need special initialization, provide a factory function (search for New* or Make* for examples) and don't export the special fields. If not, the zero value is obviously fine.

Recursive application of this simple and widely used rule negates the problem you seem to be having; F apparently needs special initialization, so it should provide an appropriate factory, then E needs special initialization (as it uses F), so it should provide… and so forth. Until the user just uses NewF, which will take care of recursive initialization. No one needs to know anything about any package they are not directly importing.

Note, that there is zero difference here, between a language with or without constructors, in terms of which code needs to be aware of what. The difference only is, that the constructors are explicit and people need to be aware of how to construct values.

--
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+unsubscribe@googlegroups.com.

Ian Lance Taylor

unread,
Jan 13, 2017, 10:03:29 AM1/13/17
to hui zhang, golang-nuts
On Fri, Jan 13, 2017 at 6:47 AM, hui zhang <fastf...@gmail.com> wrote:
> Yes , cycle import is a bad design.
> But as the software becomes larger , not everything is controllable.
> In real project , some times it is a great risk to do refactor.

Go is careful to initialize values in the correct order, such that if
the initializer for V1 refers to V2, then V2 is always initialized
before V1. It is possible to break this by calling between packages
in the initializers, but it takes a fair amount of work. If Go
permitted cyclic imports, correct initialization would be impossible.
Go has given up one feature (cyclic imports) in favor of another one
(simple and correct initialization).

Ian

simon place

unread,
Jan 13, 2017, 1:56:07 PM1/13/17
to golang-nuts
sorry but for me, excepting generics and maybe a float32 maths lib, these are all just your problem.

particularly wrong is the idea of native conversion of bools to/from numbers, albeit widespread and long-standing, perpetuating these mistakes just means preventing any development of languages.

Jesper Louis Andersen

unread,
Jan 13, 2017, 2:02:26 PM1/13/17
to Ian Lance Taylor, hui zhang, golang-nuts

For 2, out of curiosity. What is wrong with the following code using math.MaxUint32 for instance:


math defines a constant, which you will need to assign to an variable. But I don't see there being any type conversion in this piece of code. It is all implicit over the types given.

Did you allude to something else?

For 1, your workarounds are:

* Write the code yourself by hand. The work seems tedious, but one observation I have from implementing monomorphisation/defunctorisation passes in compilers is that often the number of variant uses of an abstraction is at most a handful. Even in very large programs. So there may be less code to write in the common case than what people think.

* Use a generator and generate the code. Essentially running the monomorphisation yourself as a first stage in the compiler. This is also pretty easy to do.

A side note: if you *really* care about your programs efficiency, you need a compiler which supports staged compilation, so you can stage code generation for more than just types. For instance by specializing matrix multiplications to a specific dimension and so on. This is the land of cogen as well.

--
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.

howar...@gmail.com

unread,
Jan 13, 2017, 7:08:55 PM1/13/17
to golang-nuts
Ehrmm, well, you can do that. The bit that you can't do without it being implemented in language is having it behave as a properly type-safe expression all the way through.

Here is an example of a ternary function and its use that correctly triggers side-effects down only its true path and never calls functions or triggers side-effects on the other paths. It is quite a bit more verbose than a simple ternary, and I would definitely not recommend its use, but it is an interesting example of the use of first-class functions.


There are two forms there, one that is nestable but is only a statement, and can't be used in expression context (but is more compact to write, and type-safe). The other is nestable and works as an expression, but uses interface{} and so needs casting depending on the use context.

Howard

On Friday, January 13, 2017 at 8:41:54 AM UTC-6, Michael Jones wrote:
One minor point is that you cannot fake the ternary operator with a function. In the function call the two alternates are evaluated before the call so this breaks ... everything else with side effects such as function calls.

Yu Liu

unread,
Jan 14, 2017, 1:42:43 AM1/14/17
to golang-nuts
Agree.

Only generics missing is disadvantage of Go.

Yu


On Friday, January 13, 2017 at 10:56:07 AM UTC-8, simon place wrote:

Christoph Berger

unread,
Jan 14, 2017, 4:35:33 AM1/14/17
to golang-nuts
Hi Yu,

Generics have their use cases, e.g. when designing general data containers or in the context of numeric computation (matrix type of int, float, etc). In other areas, however, their use may be overrated. 

If you have a particular problem and you think, "I do need generics to implement that!", then you might become blind for other solutions. 

Some time ago I collected a number of alternatives to using generics - see: https://appliedgo.net/generics

Best,
Christoph
Message has been deleted

Christoph Berger

unread,
Jan 14, 2017, 7:24:50 AM1/14/17
to parais...@gmail.com, golang-nuts
> None of these alternatives really solve any real problem generics would solve.

True, and the article does not mean to imply this. But often it would seem that there is no alternative to using generics for solving a given problem although there is one if you look close enough. Of course this depends on the nature of the problem to solve, and I am far from saying that generics are superfluous. 

> It's not being blind to another solution, 

Sometimes it is.

> every other solution has drawbacks generics don't have.

Generics have drawbacks, too. It’s always about pros and cons, there is no ideal approach.

> But let's not pretend than there is an alternative to generics "people can't see" within Go.

The alternatives are there, depending on the problem to solve. Agreed, there are domains  where the alternatives are cumbersome to implement, use, and/or maintain, but it is not true that there are no other options. 

> Let's not patronize people who see the obvious flaw in that logic.

If anything I wrote came across as patronizing, then I apologize. I only try to help people by pointing out other approaches. If someone is new to the language, they might not yet have heard of the techniques I listed in the article.

> people coming from Java, C# or Haskell will have harder time working around the lack of generics in Go because they are used to that feature to solve their problems. 

That’s the point. Asking why Go does not have feature X of language Y is pointless because Go is not language Y. 
Every language is the result of a series of design decisions, and so is Go. 

> To the latter I'd say that if Go feels tedious for a task then use something else, really. 

Absolutely. I see we’re on the same page here.


To add some other aspects to the discussion, in a recent talk, William Kennedy shares some very interesting thoughts about Generics:


(This link starts at minute 49:29 - ensure to watch at least past minute 54.)



Am 14.01.2017 um 12:27 schrieb parais...@gmail.com:

>  Some time ago I collected a number of alternatives to using generics - see: https://appliedgo.net/generics

None of these alternatives really solve any real problem generics would solve. Generics are types, just like first class functions. Lamenting on the lack on generics is useless as well, Go will never have generics because of forward compatibility. 

But let's not pretend than there is an alternative to generics "people can't see" within Go. Go just wasn't built for code re-use in mind or writing abstractions at all due to the lack of polymorphism in the language. So people have to write specialized code when it comes to writing logic involving containers, that's the only truth there is.

> If you have a particular problem and you think, "I do need generics to implement that!", then you might become blind for other solutions. 

It's not being blind to another solution, every other solution has drawbacks generics don't have. Code generation involve writing pre-processors and maintaining manifests, opting out of Go type system with interface{} everywhere is obviously problematic. That's not solving what generics are here for in languages such as Java C# or Haskell. Basically you are asking developers to pay a price the compiler doesn't want to pay. Let's not patronize people who see the obvious flaw in that logic.

Again while it is useless to complain, people are complaining for a good reason, it can be difficult to understand what led to the absence of generics at first place in Go design. People coming from C,Python,Javascript and Ruby might not care, people coming from Java, C# or Haskell will have harder time working around the lack of generics in Go because they are used to that feature to solve their problems. 

To the latter I'd say that if Go feels tedious for a task then use something else, really. Go wasn't designed to please people who like expressive static type systems. There are many alternatives such as D, Ocaml, ... 

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/AcUcEIOUfh8/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

as....@gmail.com

unread,
Jan 16, 2017, 3:31:22 AM1/16/17
to golang-nuts
To sacrifice simplicity of readability for simpler writing is to have never been tasked with reading a 25kloc C# project and having to open 10 windows just for the object-oriented pyramid of generic abstract partial template class factories
Reply all
Reply to author
Forward
0 new messages