Свой VPN на golang
ешил сделать свой VPN на golang. В принципе основную часть сделал:
Программа создаёт виртуальный интерфейс TUN
Подключается к VPN серверу по UDP
И передает данные из TUN на сервер, а с сервера в TUN
На сервере примерно тот же самый сценарий. Как я понял, это уже является VPN (только без шифрования, но это я добавлю). Хотелось бы дать клиенту доступ в интернет, то есть что бы на сервере IP пакеты отправлялись дальше в сеть и с сети клиенту. Это я и не понимаю, как сделать. Всё делаю под Windows.
ешил сделать свой VPN на golang. В принципе основную часть сделал:
Программа создаёт виртуальный интерфейс TUN
Подключается к VPN серверу по UDP
И передает данные из TUN на сервер, а с сервера в TUN
На сервере примерно тот же самый сценарий. Как я понял, это уже является VPN (только без шифрования, но это я добавлю). Хотелось бы дать клиенту доступ в интернет, то есть что бы на сервере IP пакеты отправлялись дальше в сеть и с сети клиенту. Это я и не понимаю, как сделать. Всё делаю под Windows.
Воспроизводится ошибка 404 при нескольких автомиграциях, где ошибка? gin
package db
import (
"awesomeGin/models"
"log"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func Init(url string) *gorm.DB {
db, err := gorm.Open(postgres.Open(url), &gorm.Config{})
DisableForeignKeyConstraintWhenMigrating: true ,
if err != nil {
log.Fatalln(err)
}
db.AutoMigrate(&models.Book{})
db.AutoMigrate(&models.Game{})
return db
}
package db
import (
"awesomeGin/models"
"log"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
func Init(url string) *gorm.DB {
db, err := gorm.Open(postgres.Open(url), &gorm.Config{})
DisableForeignKeyConstraintWhenMigrating: true ,
if err != nil {
log.Fatalln(err)
}
db.AutoMigrate(&models.Book{})
db.AutoMigrate(&models.Game{})
return db
}
Go. No packages found for open file C:\Users\user\Documents\go-discord-rpc\main.go. This file is ignored by your gopls build
Проект требует использование python2.7, с его поддержкой нет нужной библиотеки. Было принято решение использовать CGO. При добавлении пакета C для компиляции модуля в .so файл, возникает ошибка, перестает видеть пакет main. Если переставлять место импорта пакета C, то никакого результата это не дает.
package main
import "C"
import (
"time"
)
func main() {}
// export discord_rpc
func discord_rpc(details, state, largeImage, smallImage, LargeText, smallText string) {
client, err := New("938480952844386364")
if err != nil {
panic(err)
}
err = client.SetActivity(Activity{
Details: details,
State: state,
Timestamps: &Timestamps{
Start: time.Now().Add(-time.Minute * 5),
// End: time.Now().Add(time.Minute * 5),
},
Assets: &Assets{
LargeImage: largeImage,
LargeText: LargeText,
SmallText: smallText,
SmallImage: smallImage,
},
// Buttons: []dButton{
// {
// Label: "Google",
// URL: "https://youtube.com",
// },
// {
// Label: "Discord",
// URL: "https://discord.com",
// },
// },
})
if err != nil {
panic(err)
}
time.Sleep(time.Second * 30)
}
Проект требует использование python2.7, с его поддержкой нет нужной библиотеки. Было принято решение использовать CGO. При добавлении пакета C для компиляции модуля в .so файл, возникает ошибка, перестает видеть пакет main. Если переставлять место импорта пакета C, то никакого результата это не дает.
package main
import "C"
import (
"time"
)
func main() {}
// export discord_rpc
func discord_rpc(details, state, largeImage, smallImage, LargeText, smallText string) {
client, err := New("938480952844386364")
if err != nil {
panic(err)
}
err = client.SetActivity(Activity{
Details: details,
State: state,
Timestamps: &Timestamps{
Start: time.Now().Add(-time.Minute * 5),
// End: time.Now().Add(time.Minute * 5),
},
Assets: &Assets{
LargeImage: largeImage,
LargeText: LargeText,
SmallText: smallText,
SmallImage: smallImage,
},
// Buttons: []dButton{
// {
// Label: "Google",
// URL: "https://youtube.com",
// },
// {
// Label: "Discord",
// URL: "https://discord.com",
// },
// },
})
if err != nil {
panic(err)
}
time.Sleep(time.Second * 30)
}
Организация сервера на Go с использованием context
Есть такой простой сервер:
import (
"context"
"fmt"
"math/rand"
"net/http"
"time"
)
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) //Таймаут на 5 секунд
defer cancel()
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ch := make(chan string) //Для приёма ответа
go doSomeLong(ch)
select {
case <-ctx.Done(): //Если таймаут превышен
err := ctx.Err()
fmt.Println(err)
fmt.Fprint(w, "Превышен таймаут")
case str := <-ch: //Если всё нормально, то отправка клиенту сообщения из канала
fmt.Fprint(w, str)
}
}
/*Функция для симуляции долгого процесса*/
func doSomeLong(a chan string) {
sl := rand.Intn(10)
time.Sleep(time.Duration(sl) * time.Second)
a <- "Привет!"
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("SERVER START AT :8080")
http.ListenAndServe(":8080", middleware(http.DefaultServeMux))
}
Нормальна такая конструкция в каждом обработчике? Как рендерить готовые файлы?
select {
case <-ctx.Done(): //Если таймаут превышен
err := ctx.Err()
fmt.Println(err)
fmt.Fprint(w, "Превышен таймаут")
case str := <-ch: //Если всё нормально, то отправка клиенту сообщения из канала
fmt.Fprint(w, str)
}
Есть такой простой сервер:
import (
"context"
"fmt"
"math/rand"
"net/http"
"time"
)
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) //Таймаут на 5 секунд
defer cancel()
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ch := make(chan string) //Для приёма ответа
go doSomeLong(ch)
select {
case <-ctx.Done(): //Если таймаут превышен
err := ctx.Err()
fmt.Println(err)
fmt.Fprint(w, "Превышен таймаут")
case str := <-ch: //Если всё нормально, то отправка клиенту сообщения из канала
fmt.Fprint(w, str)
}
}
/*Функция для симуляции долгого процесса*/
func doSomeLong(a chan string) {
sl := rand.Intn(10)
time.Sleep(time.Duration(sl) * time.Second)
a <- "Привет!"
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("SERVER START AT :8080")
http.ListenAndServe(":8080", middleware(http.DefaultServeMux))
}
Нормальна такая конструкция в каждом обработчике? Как рендерить готовые файлы?
select {
case <-ctx.Done(): //Если таймаут превышен
err := ctx.Err()
fmt.Println(err)
fmt.Fprint(w, "Превышен таймаут")
case str := <-ch: //Если всё нормально, то отправка клиенту сообщения из канала
fmt.Fprint(w, str)
}
Как эффективно объединять строки в Go? [дубликат]
В Go строка является примитивным типом. Это означает, что она доступна только для чтения, и любая манипуляция с ней создаст новую строку.
Мне нужно много раз объединять строки, не зная длины результирующей строки, какой самый лучший способ сделать это?
Наивный способ был бы таким:
var s string
for i := 0; i < 1000; i++ {
s += getShortStringFromSomewhere()
}
В Go строка является примитивным типом. Это означает, что она доступна только для чтения, и любая манипуляция с ней создаст новую строку.
Мне нужно много раз объединять строки, не зная длины результирующей строки, какой самый лучший способ сделать это?
Наивный способ был бы таким:
var s string
for i := 0; i < 1000; i++ {
s += getShortStringFromSomewhere()
}
Стриминг tty docker-контейнера
Мне нужно реализовать функционал стриминга терминала docker контейнера, для этого я использовал ContainerLogs и построчно собирал логи из контейнера. Однако в случае использования контейнером tty у меня возникают проблемы. В таком случае, я получаю строки логов с escape кодами (отчистка терминала, строки и тд). У меня нет проблемы отобразить это в нормальном виде, однако это сложно назвать стримингом терминала контейнера с tty. К терминалу контейнера, не используя docker-api, можно подключится с помощью docker attach, но как потом стримить это, мне тоже не ясно
Хотелось бы как-то стримить своеобразный "экран терминала" контейнера, матрицу символов, однако нигде не могу найти информации по этому поводу.
Мне нужно реализовать функционал стриминга терминала docker контейнера, для этого я использовал ContainerLogs и построчно собирал логи из контейнера. Однако в случае использования контейнером tty у меня возникают проблемы. В таком случае, я получаю строки логов с escape кодами (отчистка терминала, строки и тд). У меня нет проблемы отобразить это в нормальном виде, однако это сложно назвать стримингом терминала контейнера с tty. К терминалу контейнера, не используя docker-api, можно подключится с помощью docker attach, но как потом стримить это, мне тоже не ясно
Хотелось бы как-то стримить своеобразный "экран терминала" контейнера, матрицу символов, однако нигде не могу найти информации по этому поводу.
Как избежать дедлока при переборе значений из небуферизированного канала в GO?
Всем привет, изучаю сейчас аспекты горутин и каналов в программировании на Go. У меня есть следующий код. Который запускает несколько горутин в которых идёт запись значения в канал который равен итератору i
package main
import (
"fmt"
)
func main() {
counter := 0
numbers := []int{1, 2, 3, 4, 5}
tempChannel := make(chan int)
for _, val := range numbers {
go func(val int) {
tempChannel <- val
}(val)
}
for value := range tempChannel {
counter++
fmt.Println(value)
}
fmt.Println("Counter is", counter)
}
В целом код рабочий, но в конце я получаю deadlock. с таким выводом:
1
3
2
4
5
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
Прочитал уже много информации по каналам и посмотрел много видео на ютубе по подобной реализации, во всех примерах у людей всё получается отлично, но не могу найти несоответствие в своём коде.
Всем привет, изучаю сейчас аспекты горутин и каналов в программировании на Go. У меня есть следующий код. Который запускает несколько горутин в которых идёт запись значения в канал который равен итератору i
package main
import (
"fmt"
)
func main() {
counter := 0
numbers := []int{1, 2, 3, 4, 5}
tempChannel := make(chan int)
for _, val := range numbers {
go func(val int) {
tempChannel <- val
}(val)
}
for value := range tempChannel {
counter++
fmt.Println(value)
}
fmt.Println("Counter is", counter)
}
В целом код рабочий, но в конце я получаю deadlock. с таким выводом:
1
3
2
4
5
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
Прочитал уже много информации по каналам и посмотрел много видео на ютубе по подобной реализации, во всех примерах у людей всё получается отлично, но не могу найти несоответствие в своём коде.
Не знаю как запустить программу из-за отсутствующего пакета
Пытаюсь скомпилировать свой проект:
go build .
В ответ получаю:
http_service/service.go:17:6: no required module provides package github.com/gofiber/template/html; to add it:
go get github.com/gofiber/template/html
Пытаюсь загрузить модуль:
go get github.com/gofiber/template/html
На что получаю:
go: module github.com/gofiber/template@upgrade found (v1.8.3), but does not contain package github.com/gofiber/template/html
Что мне с этим делать?
Я новичек в использовании модулей.
Пытаюсь скомпилировать свой проект:
go build .
В ответ получаю:
http_service/service.go:17:6: no required module provides package github.com/gofiber/template/html; to add it:
go get github.com/gofiber/template/html
Пытаюсь загрузить модуль:
go get github.com/gofiber/template/html
На что получаю:
go: module github.com/gofiber/template@upgrade found (v1.8.3), but does not contain package github.com/gofiber/template/html
Что мне с этим делать?
Я новичек в использовании модулей.
Странности при компиляции программы с каналами
У меня есть такой код
package main
import (
"fmt"
"time"
)
func main(){
ch := make(chan int)
go waitOneDay(ch)
go receive(ch)
time.Sleep(time.Hour * 25)
}
func send(ch chan int) {
ch <- 1
fmt.Println("Sending value to channel complete")
}
func waitOneDay(ch chan int) {
time.Sleep(24 * time.Hour)
сh <- 1
}
func receive(ch chan int) {
time.Sleep(time.Second * 1)
fmt.Println("Timeout finished")
_ = <-ch
return
}
Когда я компилирую этот код, то получаю
./prog.go:26:2: undefined: сh
То есть не распознан канал ch внутри функции waitOneDay.
Если же закоментировать функцию waitOneDay, и заменить ее на send функцию в main,
package main
import (
"fmt"
"time"
)
func main(){
ch := make(chan int)
go send(ch)
go receive(ch)
time.Sleep(time.Hour * 25)
}
func send(ch chan int) {
ch <- 1
fmt.Println("Sending value to channel complete")
}
//func waitOneDay(ch chan int) {
// time.Sleep(24 * time.Hour)
// сh <- 1
//}
func receive(ch chan int) {
time.Sleep(time.Second * 1)
fmt.Println("Timeout finished")
_ = <-ch
return
}
то код работает как надо:
Timeout finished
Sending value to channel complete
Как мне заставить функцию waitOneDay работать? Ссылка на go playground https://play.golang.com/p/OUHusxPiObA
У меня есть такой код
package main
import (
"fmt"
"time"
)
func main(){
ch := make(chan int)
go waitOneDay(ch)
go receive(ch)
time.Sleep(time.Hour * 25)
}
func send(ch chan int) {
ch <- 1
fmt.Println("Sending value to channel complete")
}
func waitOneDay(ch chan int) {
time.Sleep(24 * time.Hour)
сh <- 1
}
func receive(ch chan int) {
time.Sleep(time.Second * 1)
fmt.Println("Timeout finished")
_ = <-ch
return
}
Когда я компилирую этот код, то получаю
./prog.go:26:2: undefined: сh
То есть не распознан канал ch внутри функции waitOneDay.
Если же закоментировать функцию waitOneDay, и заменить ее на send функцию в main,
package main
import (
"fmt"
"time"
)
func main(){
ch := make(chan int)
go send(ch)
go receive(ch)
time.Sleep(time.Hour * 25)
}
func send(ch chan int) {
ch <- 1
fmt.Println("Sending value to channel complete")
}
//func waitOneDay(ch chan int) {
// time.Sleep(24 * time.Hour)
// сh <- 1
//}
func receive(ch chan int) {
time.Sleep(time.Second * 1)
fmt.Println("Timeout finished")
_ = <-ch
return
}
то код работает как надо:
Timeout finished
Sending value to channel complete
Как мне заставить функцию waitOneDay работать? Ссылка на go playground https://play.golang.com/p/OUHusxPiObA
Бот не отвечает на команды в канале Telegram
Хочу сделать так, чтобы бот мог отсылать сообщения в канал. С группами он взаимодействует, а вот с каналами нет. На канале у него есть все права.
package tg
import (
"log"
"os"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
var UserId []int64
func Telegram() (*tgbotapi.BotAPI, error) {
bot, err := tgbotapi.NewBotAPI(os.Getenv("API_KEY"))
if err != nil {
return nil, err
}
u := tgbotapi.NewUpdate(-1)
updates := bot.GetUpdatesChan(u)
go func() {
for update := range updates {
if update.Message == nil {
continue
}
if !update.Message.IsCommand() {
continue
}
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
switch update.Message.Command() {
case "start":
UserId = append(UserId, update.Message.Chat.ID)
msg.Text = "Парсер запущен."
default:
msg.Text = "Неизвестная команда."
}
if _, err := bot.Send(msg); err != nil {
log.Println(err)
}
}
}()
return bot, nil
}
Хочу сделать так, чтобы бот мог отсылать сообщения в канал. С группами он взаимодействует, а вот с каналами нет. На канале у него есть все права.
package tg
import (
"log"
"os"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
var UserId []int64
func Telegram() (*tgbotapi.BotAPI, error) {
bot, err := tgbotapi.NewBotAPI(os.Getenv("API_KEY"))
if err != nil {
return nil, err
}
u := tgbotapi.NewUpdate(-1)
updates := bot.GetUpdatesChan(u)
go func() {
for update := range updates {
if update.Message == nil {
continue
}
if !update.Message.IsCommand() {
continue
}
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
switch update.Message.Command() {
case "start":
UserId = append(UserId, update.Message.Chat.ID)
msg.Text = "Парсер запущен."
default:
msg.Text = "Неизвестная команда."
}
if _, err := bot.Send(msg); err != nil {
log.Println(err)
}
}
}()
return bot, nil
}
Как поменять go.mod, чтобы go build не просил выполнить go mod tidy
Мне нужно сменить версию go в go.mod с 1.22.3 на 1.22 Или написать так:
module main
go 1.22
toolchain go1.22.3
req...
После чего запустить go build, но при ручном изменении go build выдаёт: go: updates to go.mod needed; to update it: go mod tidy
ВАЖНО: я не могу использовать 1.22.3, мне нужен именно 1.22 для статического анализатора, иначе он не будет работать.
Я пробовал менять руками или ставить различные флаги при сборке. Игнорирования этого требования просто нет. Изменить файл просто так я тоже не могу, требование go mod tidy все равно появляется.
Мне нужно сменить версию go в go.mod с 1.22.3 на 1.22 Или написать так:
module main
go 1.22
toolchain go1.22.3
req...
После чего запустить go build, но при ручном изменении go build выдаёт: go: updates to go.mod needed; to update it: go mod tidy
ВАЖНО: я не могу использовать 1.22.3, мне нужен именно 1.22 для статического анализатора, иначе он не будет работать.
Я пробовал менять руками или ставить различные флаги при сборке. Игнорирования этого требования просто нет. Изменить файл просто так я тоже не могу, требование go mod tidy все равно появляется.
Как распечатать переменные структуры в консоли?
Как напечатать в консоли все поля этой структуры в Golang?
type Project struct {
Hash string
Name string
Data Data
Joins Joins
}
Как напечатать в консоли все поля этой структуры в Golang?
type Project struct {
Hash string
json:"hash"
Name string
json:"name"
Data Data
json:"data"
Joins Joins
json:"joins"
}
Не могу получить параметры запроса
Есть такой шаблон
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/auth", method="post">
<input type="text" name="issuer" placeholder="login">
<input type="password", name="password" placeholder="password">
<input type="text" name="service" value={{.Service}} hidden >
<input type="submit" value="login">
</form>
</body>
</html>
Он лежит на сервере по пути /auth и вызывается исключительно методом GET
router.HandleFunc("/auth", controllers.MWDisplayHTML).Methods(http.MethodGet)
Ожидаемое поведение:
Ввожу логин и пароль, нажимаю "login" и происходит запрос post на сервер.
func MWDisplayHTML(w http.ResponseWriter, r *http.Request) {
_, cancel := context.WithTimeout(context.Background(), time.Second*4)
defer cancel()
templ, err := template.ParseFiles(consts.LoginHTMLPath)
if err != nil {
log.Println(err)
return
}
description, err := getDecriptionFromReq(r)
if err != nil {
return
}
serviceTempl := CustomTemplate{Service: description}
err = templ.Execute(w, serviceTempl)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
}
На обработчике post запросов с указанного шаблона висит обработчик, который пытается получить значение полей issuer и password. Вот функция которую я вызываю в этом обработчике для получения поля issuer
func getIssuerNameFromRequest(r *http.Request) (string, error) {
uname := r.URL.Query().Get(consts.IssuerKey)
if len(uname) < consts.MinIndx {
return consts.Empty, fmt.Errorf("%s", errs.ErrNameFieldIsEmpty)
}
return uname, nil
}
Но почему то, когда я ввожу логин и пароль то r.url.query.get не находит указанного поля. Раньше все работало, не могу понять что изменилось
Есть такой шаблон
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/auth", method="post">
<input type="text" name="issuer" placeholder="login">
<input type="password", name="password" placeholder="password">
<input type="text" name="service" value={{.Service}} hidden >
<input type="submit" value="login">
</form>
</body>
</html>
Он лежит на сервере по пути /auth и вызывается исключительно методом GET
router.HandleFunc("/auth", controllers.MWDisplayHTML).Methods(http.MethodGet)
Ожидаемое поведение:
Ввожу логин и пароль, нажимаю "login" и происходит запрос post на сервер.
func MWDisplayHTML(w http.ResponseWriter, r *http.Request) {
_, cancel := context.WithTimeout(context.Background(), time.Second*4)
defer cancel()
templ, err := template.ParseFiles(consts.LoginHTMLPath)
if err != nil {
log.Println(err)
return
}
description, err := getDecriptionFromReq(r)
if err != nil {
return
}
serviceTempl := CustomTemplate{Service: description}
err = templ.Execute(w, serviceTempl)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
}
На обработчике post запросов с указанного шаблона висит обработчик, который пытается получить значение полей issuer и password. Вот функция которую я вызываю в этом обработчике для получения поля issuer
func getIssuerNameFromRequest(r *http.Request) (string, error) {
uname := r.URL.Query().Get(consts.IssuerKey)
if len(uname) < consts.MinIndx {
return consts.Empty, fmt.Errorf("%s", errs.ErrNameFieldIsEmpty)
}
return uname, nil
}
Но почему то, когда я ввожу логин и пароль то r.url.query.get не находит указанного поля. Раньше все работало, не могу понять что изменилось
Как принять сообщение от пользователя и сохранить в переменную Telegram bot?
Делаю бота на библиотеки TeleGO, и ни как не пойму как мне принять сообщение от пользователя, записать и передать в другую функцию.
В моем понимании должно быть так, с callback вызываем цепочку
Запрос цифры от пользователя
пользователь вводит и получаем переменную tag
выводим консоль значение переменой tag
Вот код который я использую.
bh.Use(func(bot *telego.Bot, update telego.Update, next th.Handler) {
bot.SendMessage(tu.Message(tu.ID(update.CallbackQuery.From.ID), "Сажи число!"))
next(bot, update)
})
task := bh.Group(th.CallbackDataEqual("addTag"))
task.Use(func(bot *telego.Bot, update telego.Update, next th.Handler) {
num := update.Message.Text
fmt.Println(num)
if len(update.Message.Text) > 0 {
next(bot, update)
}
})
// Handle updates on a group
task.HandleMessage(func(bot *telego.Bot, message telego.Message, ) {
fmt.Println(message)
})
По ошибке, я вижу, чт омы сразу получаем сообщение от бота, пользователь ввести ничего не успевает и программа падает, тк пришел указатель на nil.
[Mon May 27 14:34:18 MSK 2024] DEBUG API response sendMessage: Ok: true, Err: [<nil>], Result: {"message_id":1169,"from":{"id":6964563095,"is_bot":true,"first_name":"livsi_games_news","username":"livsi_games_news_bot"},"chat":{"id":375152786,"first_name":"\u041b\u0435\u043e\u043d\u0438\u0434","last_name":"\u0414\u0435\u043c\u0438\u043d","username":"Livsi_MD_NN","type":"private"},"date":1716809660,"text":"\u0421\u0430\u0436\u0438 \u0447\u0438\u0441\u043b\u043e!"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x118 pc=0x12bcdb2]
Делаю бота на библиотеки TeleGO, и ни как не пойму как мне принять сообщение от пользователя, записать и передать в другую функцию.
В моем понимании должно быть так, с callback вызываем цепочку
Запрос цифры от пользователя
пользователь вводит и получаем переменную tag
выводим консоль значение переменой tag
Вот код который я использую.
bh.Use(func(bot *telego.Bot, update telego.Update, next th.Handler) {
bot.SendMessage(tu.Message(tu.ID(update.CallbackQuery.From.ID), "Сажи число!"))
next(bot, update)
})
task := bh.Group(th.CallbackDataEqual("addTag"))
task.Use(func(bot *telego.Bot, update telego.Update, next th.Handler) {
num := update.Message.Text
fmt.Println(num)
if len(update.Message.Text) > 0 {
next(bot, update)
}
})
// Handle updates on a group
task.HandleMessage(func(bot *telego.Bot, message telego.Message, ) {
fmt.Println(message)
})
По ошибке, я вижу, чт омы сразу получаем сообщение от бота, пользователь ввести ничего не успевает и программа падает, тк пришел указатель на nil.
[Mon May 27 14:34:18 MSK 2024] DEBUG API response sendMessage: Ok: true, Err: [<nil>], Result: {"message_id":1169,"from":{"id":6964563095,"is_bot":true,"first_name":"livsi_games_news","username":"livsi_games_news_bot"},"chat":{"id":375152786,"first_name":"\u041b\u0435\u043e\u043d\u0438\u0434","last_name":"\u0414\u0435\u043c\u0438\u043d","username":"Livsi_MD_NN","type":"private"},"date":1716809660,"text":"\u0421\u0430\u0436\u0438 \u0447\u0438\u0441\u043b\u043e!"}
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x118 pc=0x12bcdb2]
goroutine 51 [running]:
main.botMain.func5(0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
D:/Programming/GO/telego_bot/main.go:154 +0x32
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares(0xc0001f8200, 0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:74 +0x283
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares(0xc0001f8100, 0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:90 +0x3b0
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares.func1.1()
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:76 +0x92
sync.(*Once).doSlow(0x1351691?, 0xb?)
C:/Program Files/Go/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
C:/Program Files/Go/src/sync/once.go:65
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares.func1(0x1327e00?, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...})
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:75 +0x89
main.botMain.func4(0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
D:/Programming/GO/telego_bot/main.go:148 +0xbf
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares(0xc0001f8100, 0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:74 +0x283
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdate(0xc0001f8100, 0x0?, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...})
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:50 +0x9e
github.com/mymmrac/telego/telegohandler.(*BotHandler).Start.func1()
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/bot_handler.go:100 +0x1e5
created by github.com/mymmrac/telego/telegohandler.(*BotHandler).Start in goroutine 1
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/bot_handler.go:89 +0x165
exit status 2
main.botMain.func5(0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
D:/Programming/GO/telego_bot/main.go:154 +0x32
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares(0xc0001f8200, 0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:74 +0x283
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares(0xc0001f8100, 0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:90 +0x3b0
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares.func1.1()
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:76 +0x92
sync.(*Once).doSlow(0x1351691?, 0xb?)
C:/Program Files/Go/src/sync/once.go:74 +0xc2
sync.(*Once).Do(...)
C:/Program Files/Go/src/sync/once.go:65
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares.func1(0x1327e00?, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...})
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:75 +0x89
main.botMain.func4(0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
D:/Programming/GO/telego_bot/main.go:148 +0xbf
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdateWithMiddlewares(0xc0001f8100, 0xc0001844d0, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...}, ...)
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:74 +0x283
github.com/mymmrac/telego/telegohandler.(*HandlerGroup).processUpdate(0xc0001f8100, 0x0?, {0x33dc95ba, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...})
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/handler_group.go:50 +0x9e
github.com/mymmrac/telego/telegohandler.(*BotHandler).Start.func1()
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/bot_handler.go:100 +0x1e5
created by github.com/mymmrac/telego/telegohandler.(*BotHandler).Start in goroutine 1
C:/Users/livsi/go/pkg/mod/github.com/mymmrac/[email protected]/telegohandler/bot_handler.go:89 +0x165
exit status 2
Как append() влияет на len и cap слайса (slice) в Go?
Как функция append() влияет на длину (len) и вместимость (cap) слайса (slice) в гошке. Изменения cap слайса (slice) происходят нелинейно по отношению к количеству добавленных элементов. Почему изменяется cap среза после каждого вызова append?
Также возникает вопрос, можно ли этим как-нибудь управлять?
package main
import "fmt"
func main() {
// Создаем срез с начальной длиной 0 и вместимостью 3
slice := make([]int, 0, 3)
fmt.Printf("Initial len: %d, cap: %d\n", len(slice), cap(slice)) // len: 0, cap: 3
// Добавляем первый элемент в срез
slice = append(slice, 1)
fmt.Printf("After append 1: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 1, cap: 3
// Добавляем второй элемент в срез
slice = append(slice, 2)
fmt.Printf("After append 2: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 2, cap: 3
// Добавляем третий элемент в срез
slice = append(slice, 3)
fmt.Printf("After append 3: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 3, cap: 3
// Добавляем четвертый элемент, что приводит к увеличению вместимости среза
slice = append(slice, 4)
// Здесь
fmt.Printf("After append 4: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 4, cap: 6
}
Как функция append() влияет на длину (len) и вместимость (cap) слайса (slice) в гошке. Изменения cap слайса (slice) происходят нелинейно по отношению к количеству добавленных элементов. Почему изменяется cap среза после каждого вызова append?
Также возникает вопрос, можно ли этим как-нибудь управлять?
package main
import "fmt"
func main() {
// Создаем срез с начальной длиной 0 и вместимостью 3
slice := make([]int, 0, 3)
fmt.Printf("Initial len: %d, cap: %d\n", len(slice), cap(slice)) // len: 0, cap: 3
// Добавляем первый элемент в срез
slice = append(slice, 1)
fmt.Printf("After append 1: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 1, cap: 3
// Добавляем второй элемент в срез
slice = append(slice, 2)
fmt.Printf("After append 2: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 2, cap: 3
// Добавляем третий элемент в срез
slice = append(slice, 3)
fmt.Printf("After append 3: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 3, cap: 3
// Добавляем четвертый элемент, что приводит к увеличению вместимости среза
slice = append(slice, 4)
// Здесь
cap
может удвоиться до 6, но точное значение может зависеть от реализацииfmt.Printf("After append 4: len: %d, cap: %d\n", len(slice), cap(slice)) // len: 4, cap: 6
}
проблема с import в GO
Я только учусь и не хочу понять как это работает. У меня есть 2 файла c названиями main.go и testBD.go они находятся в одной папке и поэтому в начале этих файлов написал package main В файле testBD.go содержится функция для генерации слайса с элементами чисел от 0 до 500:
package main
func GenSlice(testSlice []int) []int {
resSlice := testSlice
for i := 0; i < 500; i++ {
resSlice = append(resSlice, i)
}
return resSlice
}
func main() {
nowTime := time.Now()
nums := []int{}
fmt.Println(GenSlice(nums))
afterTime := time.Now().Sub(nowTime)
fmt.Println("Времени ушло", afterTime)
}
в функции main() я просто проверял время работы цикла А в файле main.go есть следующий код:
package main
import (
"fmt"
)
func main() {
nums := []int{}
fmt.Println(GenSlice(nums))
}
Я ожидал увидеть просто вывод чисел в слайсе от 0 до 499 но получаю ошибку
# command-line-arguments .\main.go:9:14: undefined: GenSlice
Я только учусь и не хочу понять как это работает. У меня есть 2 файла c названиями main.go и testBD.go они находятся в одной папке и поэтому в начале этих файлов написал package main В файле testBD.go содержится функция для генерации слайса с элементами чисел от 0 до 500:
package main
func GenSlice(testSlice []int) []int {
resSlice := testSlice
for i := 0; i < 500; i++ {
resSlice = append(resSlice, i)
}
return resSlice
}
func main() {
nowTime := time.Now()
nums := []int{}
fmt.Println(GenSlice(nums))
afterTime := time.Now().Sub(nowTime)
fmt.Println("Времени ушло", afterTime)
}
в функции main() я просто проверял время работы цикла А в файле main.go есть следующий код:
package main
import (
"fmt"
)
func main() {
nums := []int{}
fmt.Println(GenSlice(nums))
}
Я ожидал увидеть просто вывод чисел в слайсе от 0 до 499 но получаю ошибку
# command-line-arguments .\main.go:9:14: undefined: GenSlice
Гарантия доставки сообщений
Есть веб-приложение на React, которое регулярно обновляет данные с сервера, написанного на Go. Я использую setInterval для выполнения HTTP-запросов каждую минуту. Я переживаю о производительности и нагрузке на сервер. Существуют ли более эффективные методы для поддержания актуальности данных?
Минимальный пример:
package main
import (
"encoding/json"
"net/http"
"time"
)
type Data struct {
Message string
}
func handler(w http.ResponseWriter, r *http.Request) {
data := Data{Message: "Hello, World!"}
json.NewEncoder(w).Encode(data)
}
func main() {
http.HandleFunc("/data", handler)
http.ListenAndServe(":8080", nil)
}
Приложение на реакте:
import React, { useEffect, useState } from "react";
function App() {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch("http://localhost:8080/data");
const result = await response.json();
setData(result);
};
fetchData();
const interval = setInterval(fetchData, 60000); // Обновление данных каждую минуту
return () => clearInterval(interval);
}, []);
return (
<div>
<h1>{data ? data.message : "Loading..."}</h1>
</div>
);
}
export default App;
Есть веб-приложение на React, которое регулярно обновляет данные с сервера, написанного на Go. Я использую setInterval для выполнения HTTP-запросов каждую минуту. Я переживаю о производительности и нагрузке на сервер. Существуют ли более эффективные методы для поддержания актуальности данных?
Минимальный пример:
package main
import (
"encoding/json"
"net/http"
"time"
)
type Data struct {
Message string
json:"message"
}
func handler(w http.ResponseWriter, r *http.Request) {
data := Data{Message: "Hello, World!"}
json.NewEncoder(w).Encode(data)
}
func main() {
http.HandleFunc("/data", handler)
http.ListenAndServe(":8080", nil)
}
Приложение на реакте:
import React, { useEffect, useState } from "react";
function App() {
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
const response = await fetch("http://localhost:8080/data");
const result = await response.json();
setData(result);
};
fetchData();
const interval = setInterval(fetchData, 60000); // Обновление данных каждую минуту
return () => clearInterval(interval);
}, []);
return (
<div>
<h1>{data ? data.message : "Loading..."}</h1>
</div>
);
}
export default App;
Как отсортировать map по порядку, указанному в массиве ключей?
Есть map, а точнее map[string]int
По умолчанию, как я понял, Golang сортирует элементы по ключу в алфавитном порядке. А как отсортировать map по ключам в заданном порядке?
Этот код:
package main
import (
"fmt"
)
func main() {
output := make(map[string]int)
basket := map[string]int{
"orange": 5,
"apple": 7,
"mango": 3,
"strawberry": 9,
}
//нужный порядок
keys := []string{
"strawberry",
"mango",
"orange",
}
for _, k := range keys {
output[k] = basket[k]
}
fmt.Printf("вывод output : %+v \n", output)
}
выдаст с ключами строки в алфавитном порядке:
mango, orange, strawberry
Есть map, а точнее map[string]int
По умолчанию, как я понял, Golang сортирует элементы по ключу в алфавитном порядке. А как отсортировать map по ключам в заданном порядке?
Этот код:
package main
import (
"fmt"
)
func main() {
output := make(map[string]int)
basket := map[string]int{
"orange": 5,
"apple": 7,
"mango": 3,
"strawberry": 9,
}
//нужный порядок
keys := []string{
"strawberry",
"mango",
"orange",
}
for _, k := range keys {
output[k] = basket[k]
}
fmt.Printf("вывод output : %+v \n", output)
}
выдаст с ключами строки в алфавитном порядке:
mango, orange, strawberry
Pаспознавания адресов/геоданных из текста
Столкнулся с задачей: нужно извлекать адреса и геоданные (например, координаты или адреса) из текстов, которые пишут пользователи в жалобах. Тексты могут содержать описания улиц, домов, ориентиров и даже неточные формулировки.
Какие есть проверенные методы, библиотеки или подходы для решения подобной задачи? Интересуют варианты на различных языках программирования (особенно Python), включая машинное обучение и регулярные выражения. Буду благодарен за любые советы, рекомендации или ссылки на готовые решения!
Столкнулся с задачей: нужно извлекать адреса и геоданные (например, координаты или адреса) из текстов, которые пишут пользователи в жалобах. Тексты могут содержать описания улиц, домов, ориентиров и даже неточные формулировки.
Какие есть проверенные методы, библиотеки или подходы для решения подобной задачи? Интересуют варианты на различных языках программирования (особенно Python), включая машинное обучение и регулярные выражения. Буду благодарен за любые советы, рекомендации или ссылки на готовые решения!