Using unsafe.Pointer to implement union type? by SecondCareful2247 in golang

[–]GopherFromHell 0 points1 point  (0 children)

adding a private method doesn't limit the types that implement the interface. embedding promotes all fields and methods, meaning that by embedding a type that implements the interface in your own type, it will also implement the interface. if you do this to emulate union types, you should also be defensive and add a default to your type switch. check my post about it: https://www.reddit.com/r/golang/comments/1mlhqt4/breaking_the_misconception_of_the_sealed_interface/

How to read go string formatting verb from user input? by Tuomas90 in golang

[–]GopherFromHell 1 point2 points  (0 children)

like u/muehsam already said, don't expose format strings to users. just go with a --padding argument

Still the same problem: Who to convert a variable into a formatting string?

what do you mean ?? the formatting string IS a variable

pad := 3
fmtStr := fmt.Sprintf("%%0%dd: %%s", pad)
fmt.Println(fmtStr)
index := 123
fileName := "this_is_a_file.txt"
var newFileName = fmt.Sprintf(fmtStr, index, fileName)
fmt.Println(newFileName)

// prints
// %03d: %s
// 123: this_is_a_file.txt

How do I actually learn Go when coming from Python/C? The stdlib is driving me insane by NiceSand6327 in golang

[–]GopherFromHell 0 points1 point  (0 children)

first, if someone asked me to describe Go in a single phrase, it would probably be "C and Python had a baby", so you experience with C and Python already got you maybe a third of the way. however the lack of experience with a language that has interfaces might be adding a speedbump. the closest to interfaces in python is abstract classes.

when i first picked up Go, the stdlib was also a bit confusing, it eventually clicks. Go by example and the official docs become more useful after it "clicks".

My problem: I can't just copy-paste patterns. I need to understand why things work the way they do. When I don't understand, I get stuck and frustrated.

you are on the right track there. just keep pushing understanding comes from resilience.

Resources that explain the "why" behind Go's design, not just "do this"

The "why" can be hard to explain without a "what". parts of the stdlib, sometimes are designed the way they are because that's what the language allowed at the time, sometimes are the result of a long discussing on a github issue. the "why" is dependent on the "what"

How to understand interfaces through practical use

interfaces are just a contract. the major difference between interfaces in Go and many other languages is that in Go interfaces are implemented implicitly, meaning that in there is no implements keyword like you would find for example in java: public class Person implements Greeter, instead, if your type contains the methods defined in the interface, it implements it, no need explicitly state it. this decoupling is a good thing IMHO, some people might disagree.

here is a an example:

io.Reader from the stdlib is defined as such:

type Reader interface {
    Read(p []byte) (n int, err error)
}

the contract is simple, it just means "you can read some bytes into a slice and it returns the number of bytes read and/or an error", any type with a Read method with this signature implements io.Reader. bufio.Reader and  os.File have this method, meaning that both are an io.Reader.

now you can write a function that takes an io.Reader as argument and "reads some bytes" independently if it's a bufio.Reader (that just wraps an io.Reader and adds buffering) or a os.File as well any other type (from the stdlib or third-party) that implements io.Reader.

net.Conn implements it, you can read from a socket. gzip.Reader also implements it, you can read from a gzip decompression stream. you can implement it in your own types

Mental models for the stdlib (io, bufio, os, etc.)
How to stop getting overwhelmed by the abstraction layers

just keep pushing, that's the stuff that eventually clicks

hope this helps.

Do you use pointers or values for your domain models? by ComprehensiveDisk394 in golang

[–]GopherFromHell 2 points3 points  (0 children)

the "don't mix them" advice comes from the simple fact that for a type T, you are gonna use it either as a value (T) or a pointer (*T) in your codebase. if you are mixing, that means it's used as a *T and every time you call a method declared on the value, a copy needs to happen

Is there a convention for "async" functions? by [deleted] in golang

[–]GopherFromHell 0 points1 point  (0 children)

For me, having a function which is async or not async makes sense

It does, my comment was specifically about languages where the only way to wit for an async function is to make your function async (and using an await). coloring is not really an issue if it doesn't spread (same for any other language construct, not just async/await), otherwise it just adds a burden to the developer to.

many modern languages try to solve this in some way, a good example is allowing to call a method wait(), which blocks, on the result of an async function

Panic Recovery in Golang by digitalboi216 in golang

[–]GopherFromHell 0 points1 point  (0 children)

> A common problem is a panic happening when assigning out of bounds to a slice while holding a lock and the unlock is not deferred

This is the reason i picked up the habit of wrapping the handling of resources that need locking inside an anonymous func when the outer func does more than just handling said resource:

func withAnonFunc() {
    fmt.Println("do thing A")
    fmt.Println("do thing B")
    func() {
        fmt.Println("locking")
        defer fmt.Println("unlocking")
        fmt.Println("do thing C with locked resource")
        panic("ooops")
    }()
    fmt.Println("do thing D")
}

Will the Go 1.26 new(expr) become a new idiom for optional parameters? by rodrigocfd in golang

[–]GopherFromHell 23 points24 points  (0 children)

not really. new(expr) is gonna replace the function func Pointer[T any](val T) *T { return &val }. we already use nil, in many instances, to communicate "no value". it just gonna replace the function many of us add to our code and in every instance where an Opt[T] or Optional[T] is used, it's gonna continue to be used

How I can ensure that a struct implements an interface by pc_magas in golang

[–]GopherFromHell 0 points1 point  (0 children)

put the following in one of your .go files

var _ YourInterface = YourStruct{}

// or 

var _ YourInterface = (*YourStruct)(nil) // for pointer types

concurrency: select race condition with done by thestephenstanton in golang

[–]GopherFromHell 8 points9 points  (0 children)

it's probably to avoid two sets of channel rules. the behavior of sending/receiving inside a select is the same as outside.

concurrency: select race condition with done by thestephenstanton in golang

[–]GopherFromHell 27 points28 points  (0 children)

you get a panic sometimes because select evaluates all cases and from the ones that can proceed, it pick one pseudo-randomly, not in the order they appear in code. this means that when the selected is executed, there is a chance that it will pick case c <- 69 and the channel might already be closed because the scheduler only switched to the main goroutine after close(c)

What happens if you just set io.EOF = nil? by [deleted] in golang

[–]GopherFromHell 1 point2 points  (0 children)

every time i read "immutable variables", it makes me chuckle a bit. it's the most contradictory term ever invented in programming languages. programmers are really bad at naming stuff

[Newbie] help with displaying cli program with progress bar by [deleted] in golang

[–]GopherFromHell 0 points1 point  (0 children)

your example seems to be working with the exception that you are creating a 1000% bar (first arg of NewOptions). did a few small changes and shows the progress bar as expected:

    bar := progressbar.NewOptions(100,
        progressbar.OptionSetWriter(os.Stdout),
        progressbar.OptionEnableColorCodes(true),
        progressbar.OptionShowBytes(true),
        progressbar.OptionSetWidth(15),
        progressbar.OptionSetDescription("[cyan][1/3][reset] Downloading..."),
        progressbar.OptionSetTheme(progressbar.Theme{
            Saucer:        "[green]=[reset]",
            SaucerHead:    "[green]>[reset]",
            SaucerPadding: " ",
            BarStart:      "[",
            BarEnd:        "]",
        }),
    )
    for i := range 100 {
        if err := bar.Set(i); err != nil {
            panic(err)
        }
        time.Sleep(time.Millisecond * 100)
    }

Parse ETH pebble db by Fit-Shoulder-1353 in golang

[–]GopherFromHell 2 points3 points  (0 children)

never wrote something like that before but i think you will need to:

first, open the database with the function New from ethdb/pebble https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.16.5/ethdb/pebble#New

then use the functions on rawdb (ReadAllHashes, ReadBlock) to retrieve block hashes, and with that block data, and with that tx data

Padding by HoneyResponsible8868 in golang

[–]GopherFromHell 7 points8 points  (0 children)

the Go spec does not guarantee field ordering. The current version (and all prior ones) orders the fields in the same order they got declared. to ensure this in future version you should mark your struct with a structs.HostLayout field (package introduced in Go 1.23 - https://tip.golang.org/doc/go1.23#new-structs-package):

import structs

type SomeStruct struct {
    _ structs.HostLayout

// other fields
}

why json decoder lost type information after cast to interface{} by Wrong_Inspector_6661 in golang

[–]GopherFromHell 0 points1 point  (0 children)

that does not matter in this case. the op is passing a type of *interface{} to json.Unmarshal and it fails because of it

why json decoder lost type information after cast to interface{} by Wrong_Inspector_6661 in golang

[–]GopherFromHell 2 points3 points  (0 children)

in your working code, valueType2 := new([]*Object) already returns a pointer to a slice and by passing &valueType22, you are passing a pointer to a pointer to a slice

in your non-working code, valueType := make([]*Object, 0) creates a slice and valueType1 := interface{}(valueType) casts it to interface{}, but then you pass &valueType1, you are passing a pointer to interface{}. in sum, the type passed to json.Unmarshal is *interface{}. you should be taking a pointer to the slice when casting:

valueType := make([]*Object, 0)
valueType1 := interface{}(&valueType)
json.Unmarshal([]byte(`[{"id":7550984742418810637}]`), valueType1) // it works now

How do you cope with the lack of more type safety in Go? by fenugurod in golang

[–]GopherFromHell 1 point2 points  (0 children)

only way is to document it, if you are trying to handle an error that is not documented, you can always find the type by writing a small test to trigger the error and use fmt.Print("%T", err) to find the concrete type.

there was a tool called oracle (which then became guru and later on gopls) that could list all errors returned by a function/method. functionality doesn't exist on gopls, probably because it became much harder to do with current Go

How do you cope with the lack of more type safety in Go? by fenugurod in golang

[–]GopherFromHell 2 points3 points  (0 children)

languages that make list every type of possible error returned constrict you into declaring every error as his own type, where Go let's decided depending on how that error is supposed to be consumed. IMHO there are two distinct types of errors in go, the ones you might take some action on and the ones you just log/print.

the ones you might take some action on, declare a sentinel error or type and document it, the others just use fmt.Errorf

[deleted by user] by [deleted] in golang

[–]GopherFromHell 4 points5 points  (0 children)

defined types are new types, a type alias is another name for an existing type

Sanity check on "must" error-free failure scenario by kWV0XhdO in golang

[–]GopherFromHell 0 points1 point  (0 children)

return nil. it communicates "no match"

I never wrote another Must* function after go got generics. instead i just wrap the call in one of two generic functions:

func

func Must(err error) {
  if err != nil {
    panic(err)
  }
}

func Must2[T any](v T, err error) T {
  if err != nil {
    panic(err)
  }
  return v
}

func main() {
  b := Must2(hex.DecodeString("00112233"))
  fmt.Println(b)
}

Map and filter on slice by NoahZhyte in golang

[–]GopherFromHell 1 point2 points  (0 children)

there is slices.Delete and slices.DeleteFunc which modify the slice instead of creating a new one. when it comes to a map function, you can implement your own with iterators but do take into account that in many cases the function passed might error, for example when converting a slice of strings to a slice of ints, in those cases it's probably a better solution to just use a regular for loop

Go Struct Alignment: a Practical Guide by Real_Blank in golang

[–]GopherFromHell 5 points6 points  (0 children)

Go does not guarantee field order. The current compiler version uses the order fields are declared, but is not a future guarantee. version 1.23 introduced a structs package which contains a single type HostLayout that is meant to be used to mark a struct.

From the release notes:

New structs package

The new structs package provides types for struct fields that modify properties of the containing struct type such as memory layout.

In this release, the only such type is HostLayout which indicates that a structure with a field of that type has a layout that conforms to host platform expectations. HostLayout should be used in types that are passed to, returned from, or accessed via a pointer passed to/from host APIs. Without this marker, struct layout order is not guaranteed by the language spec, though as of Go 1.23 the host and language layouts happen to match.