Thread 106114588 - /g/ [Archived: 257 hours ago]

Anonymous
8/2/2025, 12:05:20 PM No.106114588
GxSOG3YXIAAWqxc
GxSOG3YXIAAWqxc
md5: 7999502cc5dd46424d1d984ce1908a07🔍
Looks good to me
Replies: >>106114593 >>106114613 >>106114621 >>106114757 >>106114810 >>106115015 >>106115067 >>106115141 >>106115175 >>106115288 >>106115980 >>106116716 >>106117224 >>106117512
Anonymous
8/2/2025, 12:06:07 PM No.106114593
>>106114588 (OP)
What is a?
Replies: >>106114597
Anonymous
8/2/2025, 12:06:36 PM No.106114597
>>106114593
A dick in your ass
Anonymous
8/2/2025, 12:09:58 PM No.106114613
>>106114588 (OP)
>be a go programmer
>half of your program is about stopping
just kys if you use that piece of shit language
Anonymous
8/2/2025, 12:11:31 PM No.106114621
>>106114588 (OP)
Whats mctx?
Replies: >>106114927
Anonymous
8/2/2025, 12:16:03 PM No.106114654
this is anti-pattern btw, you are supposed to wrap the error so you get a trace of reasons why something failed and not just the leaf one
Anonymous
8/2/2025, 12:34:24 PM No.106114757
shocked_pikachu
shocked_pikachu
md5: 9d34ae5313d94b3df02ea70b0ee715f0🔍
>>106114588 (OP)
>IO-heavy code is error-prone
Replies: >>106114761
Anonymous
8/2/2025, 12:35:12 PM No.106114761
>>106114757
*misses the point by a country mile*
Anonymous
8/2/2025, 12:44:37 PM No.106114810
>>106114588 (OP)
if its so bad why didn't someone just fork it and make a fixed version of golang?
Replies: >>106114863
Anonymous
8/2/2025, 12:53:15 PM No.106114863
>>106114810
They did, it's called Rust
Anonymous
8/2/2025, 1:01:52 PM No.106114927
>>106114621
nothing, what's up with you?
Anonymous
8/2/2025, 1:12:56 PM No.106115015
>>106114588 (OP)
If the code is exactly like that and it's not just to show off how retarded Go is, why not just put function calls in an array and then iterate and call each one? Then you could just write the "if err != nil" meme just once, inside the loop. Or is it not canonical?
Replies: >>106115032
Anonymous
8/2/2025, 1:15:57 PM No.106115032
>>106115015
To add to this, I think the code is made up, because when you have a pattern like this - calling methods on an object one after another - you clearly designed something wrong.
Anonymous
8/2/2025, 1:21:40 PM No.106115067
>>106114588 (OP)
Yeah, it's so much better than try...catch exception bullshit, it's one of the best things about Go. Though whoever wrote this shit is retarded.
Replies: >>106115114 >>106115418
Anonymous
8/2/2025, 1:28:19 PM No.106115114
>>106115067
This. I'm working with shitty Python now and exceptions are fucking stupid, especially when you work with people who aren't very good devs.
Replies: >>106115418
Anonymous
8/2/2025, 1:32:27 PM No.106115141
>>106114588 (OP)
merge ASAP
Anonymous
8/2/2025, 1:37:43 PM No.106115175
>>106114588 (OP)
> looks good
That’s because it’s like C.
The thing go and rust and linux and unix and windows are written in.
Anonymous
8/2/2025, 1:48:24 PM No.106115255
if err := a.argvToGitURL(); err != nil {
return fmt.Errorf("Converting argv to git url: %w", err)
}

if err := a.initStorage(mctx); err != nil {
return fmt.Errorf("Initializing storage: %w", err)
}

if err := a.initFixedName(mctx); err != nil {
return fmt.Errorf("Initializing fixed name: %w", err)
}

if err := a.runIO(mctx); err != nil {
return fmt.Errorf("Running IO: %w", err)
}

if err := a.run(mctx); err != nil {
return fmt.Errorf("Running: %w", err)
}


>initFixedName
>runIO
>run
Without context of what it is exactly supposed to I can't write good and informative error messages.
Also, returning plain error is almost always a bad idea, you should provide context of what was happening when it occurred, and this is something that should be done even in languages that have "normal" exceptions.
Anonymous
8/2/2025, 1:53:07 PM No.106115288
>>106114588 (OP)
if err = a.argvToGitURL()
return err
if err = a.initStorage(mctx)
return err
if err = a.initFixedName(mctx)
return err
if err = a.runIO(mctx)
return err
if err = a.run(mctx)
return err
Replies: >>106115382 >>106116018
Anonymous
8/2/2025, 1:56:13 PM No.106115308
I'd approve it but I'd write it the shorter simpler way if it was myself.
Anonymous
8/2/2025, 2:05:49 PM No.106115382
>>106115288
this
Anonymous
8/2/2025, 2:10:10 PM No.106115418
>>106115067
>>106115114
Whats wrong with exceptions other than "I dont like them"?
Replies: >>106115541 >>106115817
Anonymous
8/2/2025, 2:25:08 PM No.106115541
>>106115418
Not that anon, but most of the time they are just follow similar pattern as in OP picture, "catch-and-throw", sometimes with logging. Other thing is that most of languages don't really tell you whether or not function is capable of throwing exception, depending on language you will end up with random bullshit crashes, it is worth mention that some people will put such warning about such possibility in the function doc, but this is not required unless you use specific tools (ex. PHPStan, I think MyPy could do it too), Go's approach is cleaner as it forces developers of other functions to inform you about the chance of failure.
Another thing is that exceptions are prone to abuse, so you will see quite often bad developers as form of wrappers around entire function's code.
Replies: >>106115817
Anonymous
8/2/2025, 3:03:51 PM No.106115817
>>106115418
>>106115541
Exactly this.

I add the exceptions I raise in docstrings in Python, but most devs don't so you need to do something like:
```
try:
# ...
except ExceptionIKnowAbout:
# something
except Exception as e:
# hope it doesn't get here lolz
```
And then you might need to go back to check the logs when it raises, maybe have to handle that new exception etc. While if a Go function or method can return an error, it's pretty clear there's something to handle here and if it doesn't, it doesn't and that's the end of that, in theory of course, but it's clearer.
Anonymous
8/2/2025, 3:06:28 PM No.106115842
Exactly this.

I add the exceptions I raise in docstrings in Python, but most devs don't so you need to do something like:
try:
# ...
except ExceptionIKnowAbout:
# something
except Exception as e:
# hope it doesn't get here lolz

And then you might need to go back to check the logs when it raises, maybe have to handle that new exception etc. While if a Go function or method can return an error, it's pretty clear there's something to handle here and if it doesn't, it doesn't and that's the end of that, in theory of course, but it's clearer.
Anonymous
8/2/2025, 3:24:49 PM No.106115980
>>106114588 (OP)
https://go.dev/blog/errors-are-values
This is unfortunate, misleading, and easily corrected. Perhaps what is happening is that programmers new to Go ask, “How does one handle errors?”, learn this pattern, and stop there. In other languages, one might use a try-catch block or other such mechanism to handle errors. Therefore, the programmer thinks, when I would have used a try-catch in my old language, I will just type if err != nil in Go. Over time the Go code collects many such snippets, and the result feels clumsy.

Regardless of whether this explanation fits, it is clear that these Go programmers miss a fundamental point about errors: Errors are values.

Values can be programmed, and since errors are values, errors can be programmed.

Of course a common statement involving an error value is to test whether it is nil, but there are countless other things one can do with an error value, and application of some of those other things can make your program better, eliminating much of the boilerplate that arises if every error is checked with a rote if statement.

Here’s a simple example from the bufio package’s Scanner type. Its Scan method performs the underlying I/O, which can of course lead to an error. Yet the Scan method does not expose an error at all. Instead, it returns a boolean, and a separate method, to be run at the end of the scan, reports whether an error occurred. Client code looks like this:
scanner := bufio.NewScanner(input)
for scanner.Scan() {
token := scanner.Text()
// process token
}
if err := scanner.Err(); err != nil {
// process the error
}
Replies: >>106115997 >>106116144
Anonymous
8/2/2025, 3:26:25 PM No.106115997
>>106115980
The topic of repetitive error-checking code arose when I attended the autumn 2014 GoCon in Tokyo. An enthusiastic gopher, who goes by @jxck_ on Twitter, echoed the familiar lament about error checking. He had some code that looked schematically like this:
_, err = fd.Write(p0[a:b])
if err != nil {
return err
}
_, err = fd.Write(p1[c:d])
if err != nil {
return err
}
_, err = fd.Write(p2[e:f])
if err != nil {
return err
}
// and so on

We can make this cleaner, more general, and reusable by borrowing the idea from the Scan method above. I mentioned this technique in our discussion but @jxck_ didn’t see how to apply it. After a long exchange, hampered somewhat by a language barrier, I asked if I could just borrow his laptop and show him by typing some code.

I defined an object called an errWriter, something like this:
type errWriter struct {
w io.Writer
err error
}

and gave it one method, write. It doesn’t need to have the standard Write signature, and it’s lower-cased in part to highlight the distinction. The write method calls the Write method of the underlying Writer and records the first error for future reference:
func (ew *errWriter) write(buf []byte) {
if ew.err != nil {
return
}
_, ew.err = ew.w.Write(buf)
}

As soon as an error occurs, the write method becomes a no-op but the error value is saved.

Given the errWriter type and its write method, the code above can be refactored:
ew := &errWriter{w: fd}
ew.write(p0[a:b])
ew.write(p1[c:d])
ew.write(p2[e:f])
// and so on
if ew.err != nil {
return ew.err
}

This is cleaner, even compared to the use of a closure, and also makes the actual sequence of writes being done easier to see on the page. There is no clutter anymore. Programming with error values (and interfaces) has made the code nicer.
Replies: >>106116144
Anonymous
8/2/2025, 3:28:59 PM No.106116018
>>106115288
a.argvToGitURL()?
a.initStorage(mctx)?
a.initFixedName(mctx)?
a.runIO(mctx)?
a.run(mctx)?
Replies: >>106116118 >>106116240 >>106116559
Anonymous
8/2/2025, 3:42:03 PM No.106116118
>>106116018
what language has such a syntax
Replies: >>106116610
Anonymous
8/2/2025, 3:44:07 PM No.106116144
Untitled
Untitled
md5: 2742d878f197dc6b7f88287397823d20🔍
>>106115980
>>106115997
So, with this in mind, here is how I would rewrite OP:
type Step func(mctx context.Context) error
func Do(a Whatever_A_Is) error {
steps := []Step{
a.initStorage,
a.initFixedName,
a.runIO,
a.run,
}
err := a.argvToGitURL()
for _, s := range steps {
if err != nil {
return err
}
err = s(mctx)
}
return err
}
Anonymous
8/2/2025, 3:54:05 PM No.106116240
>>106116018
How do you implement "?" when you can change the order of the return values?
func fn1() (int, error) { }
func fn2() (error, int) { }

And int is a "concrete" type, what value should be in here?
Replies: >>106116610
Anonymous
8/2/2025, 4:28:13 PM No.106116559
>>106116018
Why couldn't Go do this? There's no ternary operation in Go, so they could use ? for that...
I just did some research before posting and found out that there have been several proposals for this or to fix the error checking boilerplate already
https://github.com/golang/go/issues/19991
https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md
Replies: >>106116610
Anonymous
8/2/2025, 4:33:35 PM No.106116610
>>106116118
Rust
>>106116240
>>106116559
In Rust it just works on arbitrary Result enum. That's simpler to implement consistently than on Go's pseudo-tuples.
Usually in Go convention is to make error the last return value. Maybe just enforce it for the operator to work? And if the function doesn't return error as last value then the operator would be a compile error.
Anonymous
8/2/2025, 4:47:02 PM No.106116716
>>106114588 (OP)
dont you have macros?
Anonymous
8/2/2025, 5:43:27 PM No.106117224
>>106114588 (OP)
>error management: procedural
:|
>error management: functional
:O
Anonymous
8/2/2025, 5:44:25 PM No.106117234
bool foo() {
if (!do_a()) {
goto err_a;
}

if (!do_b()) {
goto err_b;
}

if (!do_c()) {
goto err_c;
}

return true;

err_c:
undo_b();
err_b:
undo_a();
err_a:
return false;
}


LGTM
Anonymous
8/2/2025, 6:16:02 PM No.106117512
>>106114588 (OP)
You're doing it wrong tho
The "if" should be inline `if err = a.Fn(); err != nil {`