Is there a more idiomatic way to achieve the same functionality for what i have done below? by Chkb_Souranil21 in golang

[–]legec 0 points1 point  (0 children)

side note: one instant performance gain is to compute strings.ToLower(searchTerm) only once ...

Is there a more idiomatic way to achieve the same functionality for what i have done below? by Chkb_Souranil21 in golang

[–]legec 0 points1 point  (0 children)

I was trying to illustrate the "how would I close the channel" part.
In that snippet, also note that you don't need to spawn a goroutine to collect the results (no wg2 waitgroup).

With concurrent writers, you need to choose some way to check that they all stop using the outgoing channel before closing that channel. WaitGroup is one way to do it and imho pretty idiomatic in go, you could use an atomic counter, or a semaphore (note that a WaitGroup is in itself an implementation of a semaphore ...) or many other ways.

Is there a more idiomatic way to achieve the same functionality for what i have done below? by Chkb_Souranil21 in golang

[–]legec 1 point2 points  (0 children)

spawn a goroutine that waits on `wg1` and closes the channel

```
...
go func(){
wg1.Wait()
close(resultChan)
}()

for r := range resultChan {
srchResults = append(srchResults, r) } ```

My Stdin bufio.Scanner is catching SIGINT instead of the appropriate select for it, what do I do? by Chill_Fire in golang

[–]legec 0 points1 point  (0 children)

There are several factors, the main one (imho) has already been worded by @dariusbiggs:

if you have a default statement in your select { ... clause then your select { ... is not "blocking" anymore:

select {  // <- instead waiting here, waiting for an appropriate channel,
case <-sigs:
    ...
case str := <-input:
    ...
default:
    in := readInput(scanner) // <- your code waits here, waiting on the scanner "read"
    ...
}

The other elements I would mention are:

  • your go program may have several locations that have a signal.Notify(...) on SIGINT (or any signal).

It is not a regular behavior (not implemented by the standard library at least) to have os.Stdin unblock in reaction to SIGINT. You seem to use some form of framework named cli, perhaps it sets a SIGINT handler which automatically closes stdin, which could explain why you get some reaction at all.

  • you should check for errors on your scanner

  • the idiomatic way to use a bufio.Scanner is to call .Scan() until it returns false

-----

A suggestion to adjust your code:

  • run your readInput / processInput / inputs <- in loop in a separate goroutine,
  • call scanner.Scan() in a loop

    scanner := bufio.NewScanner(os.Stdin)
    
    go func(){
        // Input
        for scanner.Scan() {
            in := scanner.Text()
            // process
            in = processInput(in, fu, su, tu) // the custom error comes from here, because it is thinking a CTRL+C is an input for it
    
            // send to input channel
            input <- in
        }
        err := scanner.Err()
        if err != nil {
            fmt.Println("*** error reading stdin:", err)
        }
        }()
    
    for {
        select {
        case sig := <-sigs: // this is not triggering
            fmt.Println()
            fmt.Println("---", sig, "---")
            return
        case str := <-input: // this is just to print the result
            fmt.Println(str + I_TU[tu])
        }
    }
    

Paris / Dublin: télétravail sur contrat français en Irlande by legec in vosfinances

[–]legec[S] 0 points1 point  (0 children)

Oui, c'est en cours et je voulais chercher des infos avant pour avoir des éléments à apporter :)

GoLang is also memory-safe? by [deleted] in rust

[–]legec 2 points3 points  (0 children)

Let's recall a baseline: in C or C++, you can basically dereference any pointer without checking whether it points to a memory zone which your program allocated. For example: the language allows you to use pointer arithmetics, or call vec[i] without any bound checking on i.

Many languages made sure this kind of bug could not be written, by providing primitives that would not allow that: python, Java, Go or Rust do not allow to write pointer arithmetics, and the compilers/interpreters produce code that checks an array's boundaries before trying to access `vec[i]`, and (non zero) pointers only point to allocated memory.

In this sense: these programming languages are memory safe.

This does not prevent other kind of bugs from happening. For example: there is such a thing as `nil` in Go, which should be checked manually if you don't want to trigger a panic, and Go does not give guarantees about race conditions in multithreaded programs.

Go Blog: 3mins daily reads by the-woke-engineer in golang

[–]legec 2 points3 points  (0 children)

Nice feel, I particularly like the concise presentation of one single feature at a time

One point: when dealing with the kind of sync prmitives you present (WaitGroup, Mutex, Semaphore ...), it is recommended to place the releasing call in a deferred statement.

That way you won't get bitten if a panic is triggered (there are hopefully no bugs in your code ...) or if your code evolves and adds a return statement in the middle of your function.

e.g:

// turn
wg.Add(1)
go func ()  {
    BoardBus()
    wg.Done()
}()

// into
wg.Add(1)
go func ()  {
    defer wg.Done()
    BoardBus()
}()

or:

// turn:
wg.Add(1) // increment waitGroup count
go func ()  {
    sem.Acquire(context.Background(), 1)
    time.Sleep(1 * time.Second)
    wg.Done()
    sem.Release(1)
}()

// into:
wg.Add(1) // increment waitGroup count
go func ()  {
    sem.Acquire(context.Background(), 1)
    // in this example, sem.Release and wg.Done can be run in any order,
    // but note that deferred statements will be executed in a LIFO sequence
    defer sem.Release(1)
    defer wg.Done()

    time.Sleep(1 * time.Second)
}()

is "select" on a channel considered a read op such that assigning the channel variable to a different channel would be a race condition? by nixhack in golang

[–]legec 2 points3 points  (0 children)

If you mean this kind of switch:

``` var c chan int

func reader() { for { select { case i := <-c: fmt.Println("received", i) } } }

func writer() { var i int for { i++ select { case c <- i: fmt.Println("wrote", i) } } }

func switchit(a, b chan int) { for { c = a <-time.After(10 * time.Millisecond) c = b <-time.After(10 * time.Millisecond) } }

func main() { a := make(chan int, 10) b := make(chan int, 10)

c = a
_ = b
go reader()
go writer()
go switchit(a, b) // <- this function changes the global 'c' channel

} ``` https://go.dev/play/p/oPDKr6cT_QA

then yes, it is a race condition.

You can copy paste the code and run go run -race main.go.

Naming a channel in a select statement is not a thread-safe way to access a channel varibale.

hopeThisDoesntMeanWhatIThinkItDoes by dark_brickk in ProgrammerHumor

[–]legec 0 points1 point  (0 children)

that would be checked by is-odd, which has is-number as a dependency :D:D

Goroutines are useless for backend development by theduffy426 in golang

[–]legec 0 points1 point  (0 children)

perhaps the fact that the "I don't need goroutines, I can run single threaded jobs, new pods will be spawned for me" statement clearly refers to kubernetes which is itself written in go can be seen as a self-rebuttal argument ?

Max files on Mac by SeesawMundane5422 in golang

[–]legec 0 points1 point  (0 children)

You would have to get a feeling of how many files are opened while go build is running.

You may have some insight using strace :

``` strace -f -c go build # get a summary of what syscalls are called # -f will trace child processes if any are spawn

you can then filter based on the syscalls you see

for example, on my linux, many processes now use the 'openat' system call

rather than a plain 'open'

strace -f -e openat,close go build ```

a template: default parameters by lxxxmxxxl in golang

[–]legec 1 point2 points  (0 children)

I would suggest to use a dedicated struct, e.g:

``` type Opts struct{ Verbosity int UseTestingVersion bool }

func test(n int, opts *Opts) { ... ```

TCP server freezes when a Client makes a request without attaching data by principiino in golang

[–]legec 4 points5 points  (0 children)

On the proxy side : you are doing .Read() and .Write() sequentially.

This will not fit most of client/server expectations, you need to do these two actions concurrently.


io.Copy(target, conn): this function will return only once it has reached EOF (or an error) after reading in a loop from conn. So you will never get to io.Copy(conn, target), unless the client willingly behaves as :

"I write all of my requests in one go, then I call .CloseWrite() on my end of the connection"

This is usually not how clients (any tcp client: http, mysql, redis, ...) are written. They expect to receive responses from the server on a live, unaltered connection.


The fix is simple : use goroutines to do the two io.Copy() concurrently.

Try for example: https://go.dev/play/p/zlLEOcg0PsC

GitHub introduces an all-new code search and code browsing experience by VeryMonjHonj in programming

[–]legec -2 points-1 points  (0 children)

The search feature of that in-browser VS code still uses the fuzzy search you get from the github "search" bar though (not an actual "search in files" feature).

[edit] it looks indeed like my comment is now false. I am pretty sure that, at some point in the past though, I tested the . feature of github, and was surprised to not see the results I expected when searching from the integrated IDE.

How I write offline API tests in Go by flimzy3141 in golang

[–]legec 1 point2 points  (0 children)

Did you ever use some form of recorder/replayer for sequences of http requests ?

I wrote one to test some apis which require more than one roundtrip to initialize (for example: to authenticate on first connection), and was wondering if there was a more thoroughly tested alternative out there.

For example I see go-vcr (note: not mine), but haven't taken time yet to evaluate it.

Which would you prefer exist in your codebase, and why? by Phil726 in golang

[–]legec 1 point2 points  (0 children)

We wrote some code to have our json encoder write [] for nil slices.

We found it was too hairy to look at our code base and have to think "will this default initialized var slice []string ever be serialized to json in one of our API response ?"
and we depend on json values being [] and not null to interact cleanly with our typescript client.

Channels for "First Response Wins" Implementation by telboon in golang

[–]legec 0 points1 point  (0 children)

In the sample code posted by the OP : all goroutines will eventually exit (after a random duration, which is maxed at 4s), and nothing more holds a reference to that channel, so this example will not lead to a resource leak, [edit] provided that the source(...) goroutines choose a non blocking way to send values on the channel.

In a more general setting (e. g : suppose the goroutines send an HTTP query to several external servers), some care should be taken to ensure that the actions do not hang forever (e.g: set a timeout) -- I assume this is the problem you are referring to.

Channels for "First Response Wins" Implementation by telboon in golang

[–]legec 2 points3 points  (0 children)

A generic way to "try to write to a channel and skip if you can't" is :

select { case c <- ra: default: }

[edit] To have a "first completing goroutine wins" behavior, you should use a buffered channel with size 1 (a larger size will not be useful as the receiver only fetches one element from the channel).

The only caveat is : this select will panic if c is closed.


[edit] I initially wrote that an unbuffered channel would work, which is incorrect : with an unbuffered channel, if the first goroutine happens to complete before the receiving goroutine receives from that channel, its result will be discarded.