Golang

2421 readers
3 users here now

This is a community dedicated to the go programming language.

Useful Links:

Rules:

founded 2 years ago
MODERATORS
1
 
 

I had some free time this weekend and I've spent some of it trying to learn Go since mlmym seems to be unmaintained and I'd like to try to fix some issues in it. I ran into a stumbling block that took a while to solve and which I had trouble finding relevant search results for. I've got it solved now, but felt like writing this up in case it helps anyone else out.

When running most go commands I tried (e.g. go mod init example/hello or go run hello.go or even something as seemingly innocuous as go doc cmd/compile when a go.mod file exists) the command would hang for a rather long time. In most cases, that was about 20~30 seconds, but in one case -- trying to get it to output the docs about the compile tool -- it took 1 minute and 15 seconds! This was on a relatively fresh Linux Mint install on old, but fairly decent hardware using golang-1.23 (installed from apt).

After the long wait, it would print out go: RLock go.mod: no locks available -- and might or might not do anything else depending on the command. (I did get documentation out after the 1min+ wait, for example.)

Now, there's no good reason I could think of why printing out some documentation or running Hello World should take that long, so I tried looking at what was going on with strace --relative-timestamps go run hello.go > trace.txt 2>&1 and found this in the output file:

0.000045 flock(3, LOCK_SH)         = -1 ENOLCK (No locks available)
25.059805 clock_gettime(CLOCK_MONOTONIC, {tv_sec=3691, tv_nsec=443533733}) = 0

It was hanging on flock for 25 seconds (before calling clock_gettime).

The directory I was running in was from an NFS mount which was using NFSv3 unintentionally. File locking does not work on NFSv3 out of the box. In my case, changing the configuration to allow it to use NFSv4 was the fix I needed. After making the change a clean Hello World build takes ~5 seconds -- and a fraction of a second with cache.

After solving it, I've found out that there are some issues related to this open already (with a different error message -- cmd/go: "RLock …: Function not implemented") and a reply on an old StackOverflow about a similiar issue from one of the developers encouraging people to file a new issue if they can't find a workaround (like I did). For future reference, those links are:

2
 
 

Putz travei nos estudos de @golang simplesmente não está funcionando, mas tb não dá erro ahahah responde qq endpoint da minha API com o mesmo, mesmo que seja um endpoint que não existe ele retorna sempre o mesmo valor, no qual deveria, já que não existe, ser um 404. Não sei o que estou fazendo de errado, mas tá foda hahahah Quebrando a cabeça aqui.

3
 
 

hi there,

Star-TeX v0.7.1 is out:

After a (very) long hiatus, development of Star-TeX has resumed. Star-TeX is a pure-Go TeX engine, built upon/with modernc.org/knuth.

v0.7.1 brings pure-Go TeX → PDF generation.

Here are examples of generated PDFs:

PDF generation is still a bit shaky (see #24), but it's coming from the external PDF package we are using rather than a Star-TeX defect per se.

We'll try to fix that in the next version. Now we'll work on bringing LaTeX support to the engine (working directly on modernc.org/knuth).

4
5
11
Golang On The PS2 (hackaday.com)
submitted 3 weeks ago by [email protected] to c/golang
6
 
 

Go 1.25 simplifies the language spec by removing the notion of core types

7
17
TIL pprof is a thing (lemmy.dbzer0.com)
submitted 1 month ago by [email protected] to c/golang
 
 

Found myself trying to debug an issue with memory not being garbage collected in a program. It turns out go comes with a tool that shows you the different memory allocations and resource hogs between different goroutines. Super useful so far from what I've found on some basic debugging, but still trying to understand how the flamegraph, the visualizations when writing to a png, and some other utilities in there work.

Overall was happy to learn that there was included tooling for that purpose within go itself.

8
9
10
 
 

It appears to pass all tests, but I'm not sure if my test writing skills are necessarily that great, I semi-followed the learn go with tests eBook. I appreciate any feedback, and if this isn't an appropriate post for this community just let me know and I'll remove.

Thanks!!

*** Update *** Updated the repository to be a bit more discriptive of what the library is for and added in a small example project of it in action.

11
 
 

Applying Hexagonal Architecture to a Mid-Size Go Backend

https://sams96.github.io/go-project-layout/

I put this post together to organise some thoughts I've been having about software architecture when it comes to Go web backends.

#golang @golang

12
7
submitted 2 months ago by [email protected] to c/golang
 
 

https://github.com/theHamdiz/it

A collection of helpful error handling, performance measuring, execution retrial, benchmarking & other useful patterns for golang under one package.

Because we kinda need this shit daily and we know it!

I don’t think anything i post here would do the project justice outside of just copying the read me.

13
14
 
 

cross-posted from: https://lemmy.ml/post/25903183

I wrote a CLI tool that generates basic scaffolding for all sorts of coding projects, from Zig applications to NPM packages.

Feel free to ask questions or contribute!

15
16
 
 

cross-posted from: https://lemmy.ml/post/24744907

I rewrote some popular games for the terminal! You can play 2048, the snake game, tic-tac-toe, connect 4, and many more.

There's still a bunch of games to be made, so feel free to contribute :)

All contributions are welcome!

17
9
submitted 3 months ago* (last edited 3 months ago) by canopas_software to c/golang
 
 

Background

Imagine you’re building a Todo application using Go. Each task in your application has a status associated with it, indicating whether it’s “completed”, “archived” or “deleted”.

As a developer, you want to ensure that only valid status values are accepted when creating or updating tasks via your API endpoints. Additionally, you want to provide clear error messages to users if they attempt to set an invalid status apart from the valid ones.

Of course, you will say enums, right?

But the bad news is Go doesn’t provide enums and the good news is we can still implement it.

In this blog, we’ll explore how to effectively manage enums in Golang, including validation techniques to ensure data integrity and reliability.

Whether you are a beginner or an experienced developer, this guide aims to demystify enums and empower you to leverage their power in your Go projects.

What is Enum?

Enum is a short form of enumeration, which represents a distinct set of named constants. While languages like Java and C++ offer native support for enums, Go takes a different approach.

Instead of a dedicated enum type, Go developers use constants or custom types with iota to emulate enum-like behavior. Let’s begin!

Why Enums?

  • Enums make code more readable by providing descriptive names for values, rather than using raw integer or string constants. This enhances code clarity and makes it easier for other developers to understand and maintain the codebase.

  • Enums provide compile-time checking, which helps catch errors early in the development process. This prevents invalid or unexpected values from being assigned to variables, reducing the likelihood of runtime errors.

  • By restricting the possible values a variable can hold to a predefined set, enums help prevent logic errors caused by incorrect or unexpected values.

Defining Enums with Constants

Constants are a straightforward way to define enums in Go. Let’s consider a basic example where we define enum constants representing different days of the week.

package main

import "fmt"

const (
    SUNDAY    = "Sunday"
    MONDAY    = "Monday"
    TUESDAY   = "Tuesday"
    WEDNESDAY = "Wednesday"
    THURSDAY  = "Thursday"
    FRIDAY    = "Friday"
    SATURDAY  = "Saturday"
)

func main() {
    day := MONDAY
    fmt.Println("Today is ", day) // "Today is Monday"
} 

Simulating Enums with Custom Types and iota

While constants work well for simple enums, custom types with iota provide a more idiomatic approach in Go.

What is iota?

iota is a special identifier in Go that is used with const declarations to generate a sequence of related values automatically.

It simplifies the process of defining sequential values, particularly when defining enums or declaring sets of constants with incrementing values.

When iota is used in a const declaration, it starts with the value 0 and increments by 1 for each subsequent occurrence within the same const block. If iota appears in multiple const declarations within the same block, its value is reset to 0 for each new const block.

package main

import "fmt"

const (
    SUNDAY = iota // SUNDAY is assigned 0
    MONDAY        // MONDAY is assigned 1 (incremented from SUNDAY)
    TUESDAY       // TUESDAY is assigned 2 (incremented from MONDAY)
    WEDNESDAY     // WEDNESDAY is assigned 3 (incremented from TUESDAY) 
    THURSDAY      // THURSDAY is assigned 4 (incremented from WEDNESDAY)
    FRIDAY        // FRIDAY is assigned 5 (incremented from THURSDAY)
    SATURDAY      // SATURDAY is assigned 6 (incremented from FRIDAY)
)

func main() {
    fmt.Println(MONDAY, WEDNESDAY, FRIDAY) // Output: 1 3 5
}

Let’s rewrite the previous example using a custom type(int).

package main

import "fmt"

type Day int

const (
    Sunday Day = iota
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Saturday
)

func main() {
    day := Monday
    fmt.Println("Today is ", day) // Output: Today is 1
}

In this example, we define a custom-type Day and use iota to auto-increment the values of the constants. This approach is more concise and offers better type safety.

Optionally, we can also use like iota + 1 , if we want our constants to start from 1.

To read the full version, please visit Canopas Blog.

Feedback and suggestions are most welcome, add them in the comments section.

Follow Canopas to get updates on interesting articles!

Keep exploring and innovating!!

18
 
 

I have a situation where generics would be useful: a server (that I do not control or influence) with many API endpoints that each returns very similar json. There's an envelope with common attributes and then an embedded named substructure (the name differs in the return value of each call) of a different type.

Without generics, you could do something like:

type Base struct {
   // common fields
}

type A {
   Base
   A struct {
      // subtype fields
   }
}

type B {
   Base
   B struct {
      // subtype fields
   }
}

but then you'd need to either duplicate a bunch of API calling and unmarshalling code, or consolidate it and do a bunch of type casting and checking.

Generics to the rescue: subtypes become specific types for a general type:

type Base[T any] {
   // common fields
   Subfield T
}

type A struct {
  // subtype fields
}

type B struct {
  // subtype fields
}

It even looks cleaner! Ah, but the rub is that the marshaled field name Subfield is the same for every type: there's no way to specify a tag for a struct type so that Subfield is un/marshaled with a name specific to the type.

https://go.dev/play/p/3ciyUITYZHk

The only thing I can think of is to create a custom unmarshaller for Base and use introspection to handle the specific type.

Am I missing a less hacky (introspection is always hacky) way to set a default tag for any field of a given struct type? How would you do this?

This pattern - APIs using envelopes for data packets - is exceedingly common. I can't believe the only way to solve it on Go is by either mass code duplication, or introspection.

19
20
 
 

cross-posted from: https://lemmy.world/post/22553148

I've been working really hard on implementing a GUI Config Editor for my Mini Macro Pad project.

Mini Macro Pad (go-mmp) is a tool for creating and running macros, shortcuts, and other automated actions at the press of a button.

It works with hardware like Arduino-based macro pads or directly through a desktop GUI, making it versatile for various workflows.

21
22
17
Go Turns 15 (go.dev)
submitted 5 months ago by [email protected] to c/golang
23
 
 

I'm fairly new to go and I've recently migrated a in-memory cache from node to go for concurrency improvements, but the memory usage difference between the two are huge. I've tried to read up on the map memory model in go but haven't been able to find a reason for the difference. I can't see that I'm doing anything special, so I'm looking for guidance here.

The documents that are stored are around 8 KB in size as a JSON file. In node the memory usage for 50000 documents stored as objects is 1,5 GB, and for go maps it is 10 GB.

To me, this doesn't seem reasonable but I can't find the source of the difference. Could anyone here give their take on this?

24
25
view more: next ›