Alexander
я ньюфаг. Расскажи
Anonymous
Ты хочешь поведать про Go! ?
Anonymous
Если да, то это тоже самое что говорить, что JavaScript унаследовался от Java
🏳️ Phil
Это игрушка Пайка. Любимая игрушка Пайка. Не им написанная, о он влюбился в неё с первого взгляда с первого релиза в 1992 году, в котором он и участвовал сам. Были ещё там ветки, ещё что, но в итоге это стало его игрушкой на всю жизнь. Это язык Alef. С сильно переделанным рантаймом (с учетом того что не взлетел). Есть только две вещи, почему нельзя провести прямую линию - копирастия, google не может впрямую пиарить эту историю, и программы на Alef не будут компилиться на Go и наоборот - полная несовместимость
🏳️ Phil
Я надеюсь, вы не думаете, что Go действительно кто-то портировал на Plan9? :)) Нет, просто наработки и уши Plan9 там вычистили чуть не к 1.5 только
🏳️ Phil
Давно не смотрел - Go до сих пор точки с запятыми препроцессором расставляет?
Anonymous
А ну, так у Алефа он унаследовал только многопоточность и каналы
🏳️ Phil
🏳️ Phil
Это просто он и есть
Anonymous
Да Alef даже пофункциональнее выглядит: http://doc.cat-v.org/plan_9/2nd_edition/papers/alef/ref
🏳️ Phil
Да. Если почитать артикли того же Пайка или там Ритчи тех лет - там понятно почему
🏳️ Phil
Они там с Alef собственно зашились на работе с памятью. А с GC они не смогли придумать как реализовать часть функционала
Alexander
Любопытно, да. Посмотрел сейчас на этот Alef - да, есть много параллелей с Go. Странно, что я про него ни разу раньше не слышал
🏳️ Phil
Я на самом деле не к тому, что надо называть Go Alef'ом или там значки вешать и памятники ставить. Я только к тому, что надо понимать, что история этого языка совершенно откровенно не начинается в 2007 году. И нет, это не то чтобы "с него взяли". Это одна и та же команда разработчиков с одной и той же платформой.
🏳️ Phil
Например при вое про дженерики надо помнить, что разработчики Go знали о дженериках, когда большинство нытиков ходило разве что в подгузники, а их любимого языка (Java) ещё не было в природе.
🏳️ Phil
И использование дженериков с каналами - это не теория, а вполне себе практика. Разработчикам явно не понравившаяся
🏳️ Phil
И синтаксис кстати придумывать не надо - он есть :))))))
Anonymous
Кстати Алеф еще получил развитие в виде Limbo
Anonymous
А Go и не скрывают, что одним из вдохновителей был как раз Limbo. Так что между Go и Алефом есть родственная связь, не пойму почему Google что то там отрицает
🏳️ Phil
Кстати Алеф еще получил развитие в виде Limbo
limbo совсем не похож и он таки с опкодом и своей vm
🏳️ Phil
А Go и не скрывают, что одним из вдохновителей был как раз Limbo. Так что между Go и Алефом есть родственная связь, не пойму почему Google что то там отрицает
Это кстати забавно, учитывая, что у Limbo синтаксис сильно отличается от Go. Рантайм - да, могли очень сильно на нём наработать. С учетом правда vm
Anonymous
Сказал бы: https://www.ibm.com/developerworks/ru/library/l-inferno_plan9_3/index.html
Anonymous
Те же срезы, короткая запись для объявления переменных, туплеты, каналы и т д
🏳️ Phil
Те же срезы, короткая запись для объявления переменных, туплеты, каналы и т д
Ну это да. Логично. Опять те же разработчики. Но там он совсем не похож. И я в третий раз говорю - там vm
Anonymous
А еще он поддерживает ARC с фоллбэком на GC для циклических указателей. Впервые такое вижу
Anonymous
Код type Config struct { Name string `json:"name"` } func GetFromConfig() string { file, err := os.Open("./config.json") if err != nil { log.Fatal(err) } defer file.Close() decoder := json.NewDecoder(file) cnf := Config{} err = decoder.Decode(&cnf) if err != nil { log.Panic(err) } return cnf.Name } Вопрос, как бы мне так извернуться что-бы через GetFromConfig() получать аргумент, и возвращать его? func GetFromConfig(s string) string { ... return cnf.s Как-то так. Или если есть какие получше варианты?
Anonymous
Это запускается один раз при старте.
Anonymous
Получаю буквально три-четыре параметра из конфига.
Anonymous
Ок, второй вариант: func (config *MyConfig) GetName() string { return config.Name} Я бы завёл под конфиг свой тип, и для него бы реализовал методы, возвращающие нужные поля.
Anonymous
В том то и дело, что поля у структуры одинаковые, строка. То есть не вижу смысла писать кучу методов.
Anonymous
В том то и дело, что поля у структуры одинаковые, строка. То есть не вижу смысла писать кучу методов.
Сори, но в Go не дженериков, поэтому копипаст и кодогенерация тут - "эта норма".
Anonymous
Хотя мне есть что предложить. Если конфиг без вложенностей, можешь через reflect доставать нужное поле: func (c Config) GetField(fieldName string) string() {}
Anonymous
Но никто это не одобрит ))
Anonymous
Да при чём тут дженерики? Мне просто нужна функция, одна, которая распарсит джейсон и вернёт запрашиваемую строку из файла.
Anonymous
Да при чём тут дженерики? Мне просто нужна функция, одна, которая распарсит джейсон и вернёт запрашиваемую строку из файла.
Зачем json? Когда ты должен один раз загрузить json в структуру и уже запросы делать по структуре?
Anonymous
Но если прям такое желание брать из json, смотри пример в этой либе: github.com/buger/jsonparser
Anonymous
Так-то уже есть чем распарсить. decoder := json.NewDecoder(file) cnf := Config{} err = decoder.Decode(&cnf) Не улавливаю момент как мне подставить аргумент в return cnf.s (s это аргумент) . Пойду доку почитаю.
Anonymous
Так-то уже есть чем распарсить. decoder := json.NewDecoder(file) cnf := Config{} err = decoder.Decode(&cnf) Не улавливаю момент как мне подставить аргумент в return cnf.s (s это аргумент) . Пойду доку почитаю.
Стандартная json-либа вроде умеет только гонять данные в структуры и обратно. Соответственно, "подставить аргумент" ты можешь либо только через reflect, либо через другую либу парсинга json'а.
Anonymous
Стандартная json-либа вроде умеет только гонять данные в структуры и обратно. Соответственно, "подставить аргумент" ты можешь либо только через reflect, либо через другую либу парсинга json'а.
Всё оказалось проще. Сделал метод который просто возвращает Config: type Config struct { Name string `json:"name"` } func (cnf Config) GetFromConfig() string { file, err := os.Open("./config.json") if err != nil { log.Fatal(err) } defer file.Close() decoder := json.NewDecoder(file) err = decoder.Decode(&cnf) if err != nil { log.Panic(err) } return cnf } А что-бы получить из структуры какой то параметр, нужно так: v := Config{} v.GetFromConfig().Name Теперь сижу думаю, насколько это правильно и не криво-ли?
Slava
а ещё лучше, читать конфиг один раз при инициализации где-нибудь в main и пробрасывать внутрь
Anonymous
Ну это связано с хотелкой, не зашивать в код некоторые вещи. Например пишу бота, в config.json положил токен бота. Так как, токен может иногда меняться, то вот через внешний конфиг менять.
Anonymous
Да.
Тогда > токен может иногда меняться неверно.
Anonymous
Тогда > токен может иногда меняться неверно.
Почему не верно, написал приложение, отдал разным людям, каждый из них создал бота, в конфиг сунул свой токен.
Anonymous
Почему не верно, написал приложение, отдал разным людям, каждый из них создал бота, в конфиг сунул свой токен.
Капитан Дуров гарантирует, что токен не меняется, соответственно достаточно сам токен считать при запуске приложения.
Anonymous
Также например для конфигурации, сейчас один IP, завтра другой, сейчас например через nginx ловит, завтра сам слушает порт.
Anonymous
Капитан Дуров гарантирует, что токен не меняется, соответственно достаточно сам токен считать при запуске приложения.
Вы читали, что я написал? Я написал один раз приложение, которое можно использовать с разными токенами.
Anonymous
Поэтому внешний конфиг важен.
Slava
может проще перезапустить приложение?
Anonymous
может проще перезапустить приложение?
или вызвать из своего приложения config.Reload()?
Slava
ну или так, на SIGUSR
Anonymous
Потому, что считывать каждый раз переменные из конфига на диске - это бред.
Alexander
Вот так просыпаешься в 8 утра в воскресенье, а в чатике такая оживлённая дискуссия. Спасибо, парни! :)) То что надо под утренний чаёк :)
Anonymous
Потому, что считывать каждый раз переменные из конфига на диске - это бред.
А не бывает каждого раза! Это случается только при старте бота, всё!
Anonymous
А не бывает каждого раза! Это случается только при старте бота, всё!
Кэп, ты сам сказал "а вдруг токен поменяется".
Anonymous
может проще перезапустить приложение?
Без внешнего конфига не перезапустишь, а придётся компилить под каждого клиента, и зашивать в код его токены, айпишнеги.
Anonymous
Anonymous
Без внешнего конфига не перезапустишь, а придётся компилить под каждого клиента, и зашивать в код его токены, айпишнеги.
Давай с самого начала. Конфиг должен быть во внешнем файле и считываться один раз при запуске программы.
Anonymous
Да.
Если пользователь меняет конфиг, он либо перезапускает приложение, либо вызывает ReloadConfig()
Alexander
Ещё бы GoFlood не был мёртв ))
Мне, как новичку в программировании, много очень полезно. Продолжайте! Спасибо)
Anonymous
Что-бы понятнее было, вот начало бота: func main() { conf := Config{} bot, err := tgbotapi.NewBotAPI(conf.Config().TelegramBotToken) if err != nil { log.Fatal(err) } _, err = bot.SetWebhook(tgbotapi.NewWebhookWithCert(conf.Config().WebhooksURL+bot.Token, "public.pem")) if err != nil { log.Fatal(err) } updates := bot.ListenForWebhook("/" + bot.Token) go http.ListenAndServe(conf.Config().ListenLocal, nil) ... Тут дальше ловим апдейты.
Anonymous
Если пользователь меняет конфиг, он либо перезапускает приложение, либо вызывает ReloadConfig()
Нет, он ставит бота на сервер, в конфиге указывает токен, ип и прочее. И запускает бота.
Anonymous
Я ожидал увидеть такое: func main() { conf := LoadConfig() // считываем конфиг из файла bot, err := tgbotapi.NewBotAPI(conf.TelegramBotToken) }
Anonymous
conf.Config().TelegramBotToken что за метод Config()?
Anonymous
conf.Config().TelegramBotToken что за метод Config()?
func (cnf Config) Config() string { file, err := os.Open("./config.json") if err != nil { log.Fatal(err) } defer file.Close() decoder := json.NewDecoder(file) err = decoder.Decode(&cnf) if err != nil { log.Panic(err) } return cnf }
Anonymous
Так сделай ))
Пока не соображу как))
Anonymous
Пока не соображу как))
Функция загрузка должна выглядеть так: func LoadConfig() (c *Config, err error)