Estou usando a biblioteca gocql https://github.com/gocql/gocql para conectar-me ao cassandra. Você pode me ajudar como posso definir o gocqlDebug
sinalizador true
como desejo alguns logs de nível de depuração. gocqlDebug parece ser um pacote private . Como faço para definir isso como verdadeiro?
No exemplo do playground Golang "Clear Screen" ,
package main
import (
"fmt"
"strings"
"time"
)
func main() {
const col = 30
// Clear the screen by printing \x0c.
bar := fmt.Sprintf("\x0c[%%-%vs]", col)
for i := 0; i < col; i++ {
fmt.Printf(bar, strings.Repeat("=", i)+">")
time.Sleep(100 * time.Millisecond)
}
fmt.Printf(bar+" Done!", strings.Repeat("=", col))
}
na linha 12 usa esta sintaxe de verbo de formatação, "[%%-%vs]". Alguém pode explicar como está sendo analisado? O duplo "%%" e o "%vs" não fazem sentido para mim. Obrigado.
Tentei dividi-lo em pedaços e executá-lo com substituições literais, como para o valor col, mas não conseguiu produzir o mesmo resultado que a execução da amostra produz.
goroutine x,y
canal a, 5 capacidade do buffer Aqui está o problema: se houver uma ocasião em que quando a está cheio e x está tentando colocar um novo item em a, em x fica bloqueado. E quando chegar a hora de pegar um item de a.
É esta a ocasião em que x input e y get podem ser vistos como a ação de sincronização? Isso pode ser visto como uma interação de canal sem buffer? (eles agem simultaneamente, mas apenas colocam/obtêm itens diferentes) Assim como um canal sem buffer quando x entra e você entende.
Lamento não ter ideia de como verificar e fazer alguns testes com minha pergunta. Portanto, estou realmente ansioso por alguns insights e interpretações.
Estou escrevendo Go há algum tempo, mas recentemente precisei realmente utilizar goroutines/ações assíncronas. Estou tendo dificuldade em entender como as coisas devem funcionar.
- Eu tenho uma função principal, que é apenas o ponto de entrada para minha ferramenta cli (então ela apenas executa cmd.ExecuteContext() e verifica se há erros).
- Eu tenho um comando
project doSomething
que precisa executar algumas rotinas go em um loop for. - Não sei exatamente qual é o problema, acertei:
fatal error: all goroutines are asleep - deadlock!
mas quando penso que resolvi, meu comando parece travar para sempre (acho que isso acontece quando uma das rotinas go ocorre um erro...?) .
Alguém pode me ajudar a entender o padrão que devo implementar aqui?
principal.go
func main() {
ctx := context.Background()
if err := cmd.NewRootCommand().ExecuteContext(ctx); err != nil {
log.Err(err)
os.Exit(1)
}
}
outro arquivo.go
func NewRootCommand() *cobra.Command {
rootCmd.AddCommand(newProjectCmd())
return rootCmd
}
func newProjectCmd() *cobra.Command {
projCmd := &cobra.Command{
Use: "project",
Short: "Interact with groups",
}
projCmd.AddCommand(newDoSomethingCmd())
return projCmd
}
func newDoSomethingCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "doSomething",
Run: func(cmd *cobra.Command, args []string) {
// stuff happens here, but no go routines or anything.
err := project.DoSomething(cmd.Context())
if err != nil {
os.Exit(1)
}
},
}
return cmd
}
lastfile.go (o pacote do projeto)
func DoSomething(ctx context.Context) error {
// lots of stuff happens
err := firstFunction(ctx)
if err != nil {
return err
}
return nil
}
func firstFunction(ctx context.Context) error {
// stuff here no go routines
err := functionWithGoRoutines(ctx)
if err != nil {
return err
}
// gets called multiple times with different parameters -- at this point I want the above to FINISH though before moving on to here
err := functionWithGoRoutines(ctx)
if err != nil {
return err
}
return nil
}
// UPDATED
func functionWithGoRoutines(ctx context.Context, items []string) error {
errors := make(chan error, 0)
var wg sync.WaitGroup
for _, item := range items {
wg.Add(1)
i := item
go func() {
defer wg.Done()
out, err := doSomethingToItemThatCanReturnError(ctx, i)
if err != nil {
errors <- fmt.Errorf("erro: %v", err)
return
}
fmt.Println(out)
}()
}
wg.Wait()
close(errors)
var err error
if len(errors) > 0 {
err = fmt.Errorf("multiple errors occurred: %v", errors)
}
return err
}
Por favor, deixe-me saber se isso já foi respondido em outro lugar e eu perdi! Pelo que pude perceber, nada descrevia exatamente minha situação. Além disso, informe-me se algo não estiver claro sobre o que estou tentando fazer!
Meu objetivo final é ter uma função que percorra uma fatia e inicie uma rotina go para cada item da fatia. Quero que a rotina go de cada item tenha tempo para terminar antes de sair da função externa. Quero coletar os erros (se houver) e devolvê-los assim que todas as rotinas forem concluídas.
Também tentei criar o grupo de espera em main.go e passá-lo até minha função. Vi algum lugar onde deveria declará-lo globalmente... mas não tinha certeza de onde?
ATUALIZAR
@Burak Sedar resolveu minha pergunta original, mas percebi que em meu código tenho mais um problema/consideração.
Dentro de cada uma das rotinas go acima há outra rotina go que precisa ser executada, mas esta não retorna um erro e deve apenas ser executada em segundo plano até que a rotina go "externa" termine. Então pode simplesmente ser cancelado.
Estou fazendo isso, mas parece assumir a espera pela rotina externa e faz com que todo o comando nunca termine:
go func() {
select {
case <-ctx.Done():
return
default:
time.Sleep(30 * time.Second)
doSomethingNewThatShouldEndOnceOuterRoutineEnds(ctx)
}
return
}()
A definição é:
//comparable is an interface that is implemented by all comparable types
// (booleans, numbers, strings, pointers, channels, arrays of comparable types,
// structs whose fields are all comparable types).
// The comparable interface may only be used as a type parameter constraint,
// not as the type of a variable.
type comparable interface{ comparable }
O que a definição significa? Não é uma interface recursiva?
Eu tenho um servidor UDP simples que escuta pacotes, espera 50 milissegundos para se comportar como se houvesse uma operação em andamento e depois imprime a mensagem no terminal. Aqui está o código do servidor:
package main
import (
"fmt"
"log"
"log/slog"
"net"
"time"
)
func main() {
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:8080")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
log.Fatal(err)
}
slog.Info("UDP server listening", "addr", udpAddr, "workers", numCpu)
go startWorker(0, conn)
// Block forever
<-make(chan struct{})
}
func startWorker(id int, conn *net.UDPConn) {
slog.Info("Starting worker", "id", id)
i := 0
for {
buf := make([]byte, 1024)
_, _, err := conn.ReadFromUDP(buf)
if err != nil {
slog.Error("failed to read UDP message", "err", err, "worker", id)
continue
}
time.Sleep(50 * time.Millisecond)
fmt.Print(i, " > ", string(buf))
i += 1
}
}
Eu tenho um código de cliente go que simplesmente envia uma mensagem de string para este servidor uma vez. Aqui está o código do cliente:
package main
import (
"log"
"net"
)
func main() {
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:8080")
if err != nil {
log.Fatal(err)
}
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
log.Fatal(err)
}
// Send a message to the server
_, err = conn.Write([]byte("Hello UDP Server\n"))
if err != nil {
log.Fatal(err)
}
}
Eu queria testar quantos pacotes podem ser manipulados no servidor. Então, o que fiz foi executar o código do cliente 10.000 vezes sequencialmente para ver quantos deles serão tratados. Mas sempre, apenas cerca de 400-500 pacotes são processados. Aqui está como fiz o teste no terminal:
time (for i in $(seq 10000); do ./client; done)
Não houve logs de erros e a saída foi:
real 0m12,538s
user 0m10,667s
sys 0m4,014s
Presumi que isso poderia ser um problema devido às limitações do buffer do sistema operacional. Então adicionei o seguinte código antes go startWorker(id, conn)
no código do servidor:
// 1 GB
if err = conn.SetReadBuffer(1024 * 1024 * 1024); err != nil {
log.Fatal(err)
}
Depois de fazer exatamente o mesmo teste, o número de pacotes processados passou de 600 a 700. Não há como 1 GB de buffer não ser suficiente para 10.000 desta simples mensagem "Hello UDP Server\n". Alguém pode me explicar o motivo desse comportamento e como posso corrigi-lo?
PS : Estou usando Ubuntu 22.04
Minha função é um arquivo de trabalho com esta assinatura
func GetFileMetadata(f *multipart.FileHeader) *FileMetadata {
d := new(FileMetadata)
// ...
if typ, err := GetFileRealType(f); err == nil {
d.Type = typ.MIME.Value
fileExt = "." + typ.Extension
} else {
d.Type = "unknown"
}
return d
}
Com a assinatura a seguir, isso não acontece.
func GetFileMetadata(f *multipart.FileHeader) (d *FileMetadata) {
// ...
if typ, err := GetFileRealType(f); err == nil {
d.Type = typ.MIME.Value
fileExt = "." + typ.Extension
} else {
d.Type = "unknown"
}
return
}
Obtendo a desreferência do ponteiro nulo , erro. Qual é a razão?
Encontrei um problema interessante ao trabalhar com números inteiros grandes no Rust and Go. Especificamente, os resultados das operações de divisão diferem entre as duas línguas quando se trata de dividendos negativos. Aqui está o código para ambos os idiomas:
Ferrugem
use num_bigint::BigInt;
use std::str::FromStr;
fn main() {
let n = BigInt::from_str("-4068122527548036313624952687320999183219209139149389824425650628448701979991259532638609685663741905551578447595775644964695361846038949186131821248175179900695219937607954907860922507949244416").unwrap();
let d = BigInt::from_str(
"115792089237316195423570985008687907852837564279074904382605163141518161494337",
)
.unwrap();
let res = &n / &d;
println!("res:{}", result);
}
Ir
package main
import "math/big"
func main() {
var n, d, res big.Int
n.SetString("-4068122527548036313624952687320999183219209139149389824425650628448701979991259532638609685663741905551578447595775644964695361846038949186131821248175179900695219937607954907860922507949244416", 10)
d.SetString("115792089237316195423570985008687907852837564279074904382605163141518161494337", 10)
res.Div(&n, &d)
println("res:", res.String())
}
Saída
Ferrugem:-35132991850681684771865987637349505035135798334672277824131793024179346079627919418184483600280933255791109974931548
Ir:-35132991850681684771865987637349505035135798334672277824131793024179346079627919418184483600280933255791109974931549
Como você pode ver, Rust arredonda o resultado para zero, enquanto Go arredonda para infinito negativo. Alguém pode explicar por que existe essa diferença e se existe uma maneira de alinhar o comportamento dessas duas linguagens em tais operações de divisão?
- Estou usando VSCode
1.87.2
, o sistema operacional é Ubunu 23.10 - Usando a extensão Go
v0.41.2
- Desativei todas as outras extensões para fins de teste
- Usando
go1.21.0 linux/amd64
Eu escrevo este trecho de código em meus *.go
arquivos Golang:
switch {
case myString == "":
fmt.Println("Empty string")
case myString == "foo":
doFoo()
case myString == "bar":
fmt.Println("We got bar now!")
default:
fmt.Println("Another default")
}
E o código VS está formatando-o como:
switch {
case myString == "":
fmt.Println("Empty string")
case myString == "foo":
doFoo()
case myString == "bar":
fmt.Println("We got bar now!")
default:
fmt.Println("Another default")
}
Pergunta, existe uma maneira de configurar a extensão VSCode / Go / outro de maneira RAZOÁVEL (ou seja, sem ter que escrever minha própria extensão do VS Code ou hackear configurações estranhas incomuns) para que a formatação do snippet 1 possa ser preservada?
O que eu tentei:
- Formatadores testados:
gofumpt
,gofmt
,goimports
- Tentei desativar todas as extensões (exceto go).
Não tenho certeza do que está errado.
Eu sou novo em Golang, tentando implementar algumas das estruturas de dados e algoritmos nele,
Eu escrevi uma função go que adiciona dados à lista, mas por algum motivo ela entra em loop infinito, já tentei várias abordagens sem sucesso, também acabei procurando o código real para Linked List na internet e encontraram várias implementações, mas todas ficaram presas no mesmo lugar,
Meu código
// linked-list.go
type Node struct {
data int
next *Node
}
type LinkedList struct {
head *Node
}
func (ll *LinkedList) Add(value int) {
node := &Node{
data: value,
}
if ll.head == nil {
ll.head = node
}
curr := ll.head
for curr.next != nil { // this is where the code gets stuck
curr = curr.next // this is not pointing it to the next node
}
curr.next = node
}
// main.go
func main() {
ll := modules.LinkedList{}
ll.Print()
ll.Add(1)
ll.Add(2)
ll.Print()
}
Alguns dos códigos que experimentei na internet