• Не получается передать структуру в html шаблон. Что я делаю не так?

    @falconandy
    Явно же написано: role is an unexported field of struct type main.Client
    Идентифакторы с маленькой буквы являются неэкспортируемыми, нужно переименовать поля role/ip в Role/Ip и всё должно получиться.
    Ответ написан
    1 комментарий
  • Где допустил ошибку при работе Golang pgx с postgresql?

    @falconandy
    Сначала залоггируйте full_text, возможно он приходит пустой и pgx ни при чем.
    full_text := r.FormValue("full_text")
    log.Print(full_text)


    Не работал с pgx, но обычно для Insert используют Exec вместо Query, хотя возможно нет никакой разницы.
    Ответ написан
  • Как считывать из бесконечного Stdout?

    @falconandy
    1. Т.к. питоновский скрипт работает вечно, я думаю, вам надо в отдельной горутине выдавать прочитанные строки в канал.
    2. Вы забыли запустить сам питоновский скрипт.
    3. Питон по умолчанию буферизирует вывод, можно добавить флаг -u для отключения буферизации.

    Что-то типа:
    package main
    
    import (
    	"bufio"
    	"os/exec"
    )
    
    func main() {
    	lines := read()
    	for line := range lines {
    		print(line)
    	}
    }
    
    func read() <-chan string {
    	lines := make(chan string)
    
    	go func() {
    		defer close(lines)
    
    		child := exec.Command("python", "-u", "./test.py")
    
    		stdout, err := child.StdoutPipe()
    		if err != nil {
    			return
    		}
    
    		err = child.Start()
    		if err != nil {
    			return
    		}
    		println("Started")
    
    		reader := bufio.NewReader(stdout)
    
    		for {
    			line, err := reader.ReadString('\n')
    			if err != nil {
    				break
    			}
    
    			lines <- line
    		}
    
    		err = child.Wait()
    		if err != nil {
    			println(err)
    		}
    	}()
    
    	return lines
    }
    Ответ написан
  • Почему не видно лог?

    @falconandy
    1. Канал quit не нужен - можно заменить на выход из цикла:
    Loop:
    	for {
    		...
    			if count == 10 {
    				break Loop
    			}
    		...
    	}
    
    	log.Println("quit")


    2. Тикер первый раз сработает не сразу, а только через 60 секунд (а main спит только 10 секунд). Надо разобраться с задержками, чтобы они соответствовали друг другу, или в main ждать не за счет sleep, а более явно (WaitGroup возможно).
    Ответ написан
    Комментировать
  • Что не так с потоками?

    @falconandy
    С "потоками" всё так, просто вы неправильно работаете с "массивом".

    perftracing = append(perftracing, 0) при исчерпании выделенной памяти выделяет новый блок памяти (по-моему удвоенного размера) и копирует текущие элементы в новый блок. Соответственно часть (половина) горутин пишет по старым адресам, а в выхлопе данные из последнего выделенного блока памяти.

    ...
    0 0 0 0 5197273 5671085 5177800 5797080 
    0 0 0 0 5197332 5671147 5177908 5797137 
    0 0 0 0 5197388 5671208 5178008 5797195 
    0 0 0 0 5197450 5671269 5178118 5797248
    ...


    Если создать "массив" заранее со всеми элементами, то всё выводится нормально:
    threads := 4
    perftracing := make([]int64, threads)
    for i := 0; i < threads; i++ {
    	go thread(&perftracing[i])
    	time.Sleep(1)
    }


    ...
    5593758 7107822 5575001 6449763 6321574 5535152 5728000 7196092 
    5593813 7107884 5575056 6449859 6321628 5535209 5728060 7196153 
    5593879 7107959 5575122 6449976 6321695 5535275 5728122 7196217 
    5593936 7108030 5575180 6450079 6321757 5535339 5728190 7196285 
    ...
    5594008 7108109 5575251 6450199 6321821 5535403 5728251 7196349


    Ну и вместо time.Sleep(1) вы наверно имели в виду что-то типа time.Sleep(time.Second * 1)

    Go 1.19.3, Kubuntu 22.04
    Ответ написан
    Комментировать
  • Как в Golang проверить вхождение строки в строку, но слово целиком?

    @falconandy
    Проще регуляркой, но не факт, что быстрее и покрывает все кейсы:
    package main
    
    import (
    	"fmt"
    	"regexp"
    )
    
    func main() {
    	text := "something, something1, othersomething"
    
    	fmt.Println("some", createWordRegex("some").MatchString(text))
    	fmt.Println("thing", createWordRegex("thing").MatchString(text))
    	fmt.Println("something", createWordRegex("something").MatchString(text))
    	fmt.Println("something1", createWordRegex("something1").MatchString(text))
    }
    
    func createWordRegex(word string) *regexp.Regexp {
    	return regexp.MustCompile(`\b` + regexp.QuoteMeta(word) + `\b`)
    }
    Ответ написан
    2 комментария
  • Почему проходит тест с моком при любом возвращаемом значении?

    @falconandy
    Есть тест, который тестирует умножение 5 на 5 и я хочу проверить что возвращается именно 25


    Если вы хотите протестировать логику метода
    func (m multiplier) Calculate(num int, times int) int
    , то мок вам не нужен - тестируйте этот метод без всяких моков.

    Если же вы хотите протестировать логику функции func CalculateFiveTimesFive(m Multiplier) int, то должны проверить в тесте, что она возвращает. При этом мок не обязан возвращать именно 25, а может вернуть любое число. По сути вы проверяете, что функция CalculateFiveTimesFive всегда возвращает результат вызова метода Calculate - такой тест выглядит довольно бесполезным (как и сама функция CalculateFiveTimesFive).

    m.On("Calculate", 5, 5).Return(37)
    assert.Equal(t, 37, multiplier.CalculateFiveTimesFive(m))
    m.AssertExpectations(t)
    Ответ написан
    Комментировать
  • Golang Stepik 3.9 Параллелизм ч.2 как решить?

    @falconandy
    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	arguments := make(chan int)
    	done := make(chan struct{})
    	result := calculator(arguments, done)
    	for i := 0; i < 10; i++ {
    		arguments <- 1
    	}
    	close(done)
    	fmt.Println(<-result)
    }
    
    func calculator(arguments <-chan int, done <-chan struct{}) <-chan int {
    	output := make(chan int)
    
    	go func(output chan int) {
    		defer close(output)
    
    		var x int
    	Loop:
    		for {
    			select { // Оператор select
    			case arg, ok := <-arguments: // Ждет, когда проснется гофер
    				if !ok {
    					break Loop
    				}
    				x += arg
    				fmt.Println(x)
    			case <-done: // Ждет окончания времени
    				break Loop
    			}
    		}
    		output <- x
    	}(output)
    
    	return output
    }
    Ответ написан
  • Как подавить предупреждения от С библиотеки в Golang?

    @falconandy
    Нагуглил https://github.com/zimmski/osutil/blob/master/capt..., не проверял - может быть подойдет как идея реализации.
    Ответ написан
    Комментировать
  • Почему при чтении из канала с циклом появляется задержка в начале работы?

    @falconandy
    1. появляется задержка в начале работы - не понял, что за задержка. Поясните по возможности
    2. status_Ch := <-myChan для закрытого канала будет возвращать zero-значание (в данном случае 0) и цикл никогда не завершится. Проще всего переделать на for status_Ch := range myChan
    3.
    var testStatus = 200 // Тест-статус результата (меняется непредсказуемо с каждой итерацией цикла): 100 - успешно; 200 - неудачно.
    - вроде testStatus нигде не меняется
    Ответ написан
    3 комментария
  • Как правильно установить несколько версий го на одной системе?

    @falconandy
    Есть простой официальный способ, если он вам подходит. Бинарники будут называться типа go1.10.7
    Ответ написан
    Комментировать
  • Как узнать когда горутины закончили запись, чтобы закрыть канал?

    @falconandy
    Примерно так: https://goplay.tools/snippet/TciyGAE8dyn
    Ответ написан
    Комментировать
  • Как сделать вывод массива со сдвигом?

    @falconandy
    1. Строка text = '' * maximum + text выглядит бесполезной - для чего пустую строку пытаться реплицировать?
    2. Выхлоп вашего скрипта (на Python 3, но это не должно вроде влиять) отличается от вами приведенного. Не хватает укорачивания строк:
    ...
    wxxyyzz0011223344556677889900
    xxyyzz0011223344556677889900
    xyyzz0011223344556677889900
    yyzz0011223344556677889900
    yzz0011223344556677889900
    zz0011223344556677889900
    z0011223344556677889900
    0011223344556677889900
    011223344556677889900
    11223344556677889900
    1223344556677889900
    223344556677889900
    23344556677889900
    3344556677889900
    344556677889900
    44556677889900
    4556677889900
    556677889900
    56677889900
    6677889900
    677889900
    77889900
    7889900
    889900
    89900
    9900
    900
    00
    0

    3. Для текущей версии аналог на Go:
    package main
    
    func main() {
    	text := "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz0011223344556677889900"
    	show(text, 30)
    }
    
    func show(text string, maximum int) {
    	for i := range text {
    		if i+maximum < len(text) {
    			println(text[i : i+maximum])
    		} else {
    			println(text[i:])
    		}
    	}
    }
    Ответ написан
    1 комментарий
  • Проблема с range. Как решить?

    @falconandy
    Поменяйте имена полей структуры - начните их с заглавной буквы, чтобы сделать публичными (например, Name string).
    Ответ написан
    Комментировать
  • Не будет гонки и повреждения данных в памяти?

    @falconandy
    По-моему вы переусложняете без необходимости. Если значения из конфига только читаются, то потокобезопасность не нужна. Если же у вас предполагается еще и изменение, то в пул возвращаются указатели на "порченные" объекты, что тоже неправильно.
    Если возможно, конфиг лучше прочитать в начале выполнения, а также паниковать на уровне main.
    В результате и код проще, и тормозить нечему:
    package config
    
    import (
    	"encoding/json"
    	"fmt"
    	"os"
    )
    
    type Cfg struct {
    	// Fields
    }
    
    var (
    	cfg *Cfg
    )
    
    func Config() *Cfg {
    	return cfg
    }
    
    func LoadConfig() error {
    	f, err := os.Open("./config/config.json")
    	if err != nil {
    		return fmt.Errorf("can't open config file: %w", err)
    	}
    	defer f.Close()
    
    	dec := json.NewDecoder(f)
    	var c *Cfg
    	if err := dec.Decode(c); err != nil {
    		return fmt.Errorf("can't decode config file: %w", err)
    	}
    
    	if err := validate(c); err != nil {
    		return fmt.Errorf("can't validate config file: %w", err)
    	}
    	
    	cfg = c
    
    	return nil
    }
    
    func validate(cfg *Cfg) error {
    	// Logic
    	return nil
    }
    Ответ написан
    Комментировать
  • Горутино-безопасное обоащение к sqlite3?

    @falconandy
    Можно ограничить максимальное кол-во соединений до 1:
    db.SetMaxOpenConns(1)
    Это приведет к тому, что и запросы на чтение перестанут выполняться параллельно - так что может подойти, если у вас запросы "шустрые".
    Плюс в том, что в коде не надо будет ничего менять, никаких мьютексов.
    Но так как у вас мест записи в БД немного, то можно использовать и мьютексы - вряд ли вы что-то упустите.
    Если бы мест изменения БД было много, то еще можно рассмотреть вариант обертки над *sql.DB, в которой автоматически использовать мьютекс для всех "подозрительных" методов - например Exec методов (из предположения что в них как правило идет изменение БД) или Query методов, если в запросе есть insert, update или delete.

    Вот еще ссылка по теме: https://stackoverflow.com/questions/35804884/sqlit...
    Ответ написан
    Комментировать
  • Нужна помощь с кросс компиляцией бинарника под разные системы Linux?

    @falconandy
    Можно переписать на Go и скомпилировать статический бинарник без зависимостей.
    https://www.arp242.net/static-go.html
    В только что зарелизенном Go 1.15 размер бинарника будет поменьше чем на предыдущих версиях.

    Для компиляции 32-битной версии просто устанавливайте пару переменных:
    GOOS=linux GOARCH=386 go build
    Ответ написан
  • Порядок действий для оформления самозанятого, для иностраных платежей и выбор банка?

    @falconandy
    Мой недавний опыт
    1. На сайте Альфа-банка заказал бесплатную дебетовую карту с выдачей в отделении (отделение выбрал центральное с "моментальной" выдачей). Альфа-банк, потому что в моем регионе у них есть банкоматы с приемом/выдачей валюты. Заранее установил мобильное приложение Альфа-банка. Через пару часов туда подъехал, по-моему по моей заявке еще никто ничего не делал. Поинтересовались, для чего мне их карта и выдали мне именную рублевую дебетовую карту (в заявке указывал MasterCard, но принесли Visa - мне было непринципиально), и дополнительно я попросил долларовую (собственно для этого я и забирал лично, хотя можно было заказать доставку) - выдали неименную. Мобильное приложение Альфы понадобилось, чтоб тут же активировать карты. Всё заняло минут 20-25, но мои данные у них уже были, несколько лет назад я получал через них зарплату.
    2. Зарегистрировался как самозанятый через веб-доступ налоговой (в моем регионе доступно с июля 2020 г.).
    3. Установил мобильное приложение Мой Налог. В мобильном приложении Альфа-банка зарегистрировался как уже зарегистрированный самозанятый.
    4. Добавил 2 новых счета (рублевый и долларовый), назвал их, чтоб было понятно что они для учета доходов от самозанятости.
    5. Добавил эти счета в Upwork (рублевый "Direct to Local Bank" и долларовый "Wire Transfer")
    6. С рублевым счетом проблем не было, а в долларовом не совпало моё имя (в Альфе было еще отчество и транслитерация одной буквы не совпадала) - отправил запрос в поддержку Upwork и счет в течение нескольких часов одобрили.
    7. Добавленные счета становятся доступными для вывода через 3 дня.
    8. Через 3 дня вывел в долларах через "Wire Transfer", на счет Альфы пришло на следующий день. Никакого явного валютного контоля не было, документы не просили, комиссий не снялось (только $30 снял Upwork как и положено).
    9. Самостоятельно посчитал пришедшую сумму в рублях по курсу ЦБ на дату получения денег на счет.
    10. В мобильном приложении Альфы создал новый чек от иностранной организции (Upwork Global Inc.), указал сумму в рублях. Проверил в приложении Мой Налог, что чек нормально ушел и начислился налог (по факту реального налога пока нет, т.к. действует налоговый бонус около 22000 руб. = 10000 руб + чуть больше 12000 руб.)
    11. На всякий пожарный случай: скачал шаблон Confirmation of Service, заполнил и отправил в поддержку Upwork. Полученный от них подписанный экземпляр сохранил.
    Ответ написан
  • Аналог electron только на GO?

    @falconandy
    Гляньте на

    A tiny cross-platform webview library for C/C++/Go... It uses Cocoa/WebKit on macOS, gtk-webkit2 on Linux and Edge on Windows 10.

    A very small library to build modern HTML5 desktop... It uses Chrome browser as a UI layer. Unlike Electron it doesn't bundle Chrome into the app package, but rather reuses the one that is already installed.
    Ответ написан
    Комментировать