Задать вопрос
  • Перенести ветку мастер в другой репозиторий?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Если master который был в новой репе не нужен, то следующих команд должно быть достаточно:
    git remote add new <url_new_repo>
    git push new +master
    Ответ написан
    3 комментария
  • Не получается протестить handler используя *gin.Gonic?

    @12rbah
    Handler-ы находятся в другом пакете.
    Тестировать можно в том же пакете, но в целом это не важно, если только вы не делаете их приватными.

    И вот вопросом в том, требуется ли мне дополнительная функция, которая бы возвращала *gin.Engine, чтобы я мог в тестововм файле запускать спокойно сервер

    Нет не нужна. тут есть пример

    Для простых случаев получится примерно так
    func testHTTPResponse(t *testing.T, r *gin.Engine, req *http.Request, f func(w *httptest.ResponseRecorder) bool) {
    
    	w := httptest.NewRecorder()
    
    	r.ServeHTTP(w, req)
    
    	if !f(w) {
    		t.Fail()
    	}
    }
    
    func TestApiHandler(t *testing.T) {
    
    	var a apiService
    	router := gin.Default()
    	router.GET("/api/login",a.SignIn)
    	req, err := http.NewRequest("GET", "/test", nil)
    	if err != nil {
    		t.Fatal(err)
    	}
    	testHTTPResponse(t, router, req, func(w *httptest.ResponseRecorder) bool {
    		statusOK := w.Code == http.StatusOK
    
    		p, err := ioutil.ReadAll(w.Body)
    		pageOK := err == nil && strings.Index(string(p), "<title>Register</title>") > 0
    		return statusOK && pageOK
    	})
    
    }

    p.s. для случаев с аутентификацией/всякими токенами, тестировать будет труднее
    Ответ написан
    1 комментарий
  • На какую зарплату может рассчитывать junior golang developer?

    dmitrichenko
    @dmitrichenko
    CEO/Founder - GetMatch.ru
    Можно оттолкнуться от зарплат middle go разработчиков, сейчас это ~200 - 300k net. Примеры golang вакансий

    Для джуна стоит ориентироваться на вилку 100 - 150k.

    Чтобы следить за вакансиями и зарплатами в IT, подключите getmatch в телеграме или смотрите на сайте https://getmatch.ru/
    Ответ написан
    1 комментарий
  • Что дальше учить?

    @As56
    Просто учить смысла нет. Нужно четко и конкретно понимать для чего тебе это нужно - что ты собираешься с этими знаниями делать, любые знания, которые не используются, успешно забываются. И да, надо не учить, а изучать, т.е. знать что и где применяется, как применяется, где можно посмотреть подсказки, где попрактиковаться, где отслеживать тенденции данной сферы, с кем общаться(а общение с единомышленниками очень важно) и т.д.
    В данной ситуации, я думаю, важно определиться со специализацией. Или это фронтенд, или бэкэнд, или full-stack. У каждого пути свои необходимые знания и фреймворки. Исходя из того чем бы ты хотел заниматься дальше, нужно и выбирать что изучать.
    Ответ написан
    Комментировать
  • На какую зарплату может рассчитывать junior golang developer?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    От 0 до средней мидловой у goшника. Зависит от того, в какую компанию вам повезло попасть, вашей ценности для этой компании и умения себе продавать.
    Ответ написан
    1 комментарий
  • LDAP with Golang (создать сервер) как?

    Забыли ковычки http.ListenAndServe(":389", nil)
    Ответ написан
    1 комментарий
  • Почему кнопка срабатывает со второго раза?

    @Scoo909010
    likesById нужно вызывать в useEffect, потому что это асинхронная операция.
    Ответ написан
    1 комментарий
  • INSERT INTO при тестировании через sqlmock?

    kvaks
    @kvaks
    для INSERT нужно добавлять результат и не забывай про обрамлять слешом SQL запросы в mock (regex online)

    вот пример кода
    mock.ExpectExec(`INSERT INTO Products \(model, company, price\) values \('\$1', \$2, \$3\)`).
    				WithArgs(tt.args.model, tt.args.company, tt.args.price).
    				WillReturnResult(sqlmock.NewResult(1, 1))
    Ответ написан
    1 комментарий
  • RabbitMQ: вопрос по consumer-у?

    @yarkin
    Куда происходит публикация сообщения, в обменник? Кто создаёт очередь и биндинг на обменник? Может ли такое случиться, что если очередь и биндинг создаёт консьюмер, то в момент их создания обменника ещё не существует и происходит ошибка, которая игнорируется? Раз есть management плагин в контейнере, можно посмотреть состояние системы в момент, когда сообщения не получаются консьюмером: есть ли очередь, обменник, бингдинг между ними, консьюмер очереди.
    Но тоже не забывайте, что если в первую очередь стартует паблишер, а потом консьюмер, то при отсутсвующих очередях можно потерять сообщения. В идеале создавать всю инфраструктуру обменников и очередей должен какой-то скрипт инициализации, до старта основных приложений (что-то схожее с запускам миграции БД). Но такое так же можно сделать с помощью самого RabbitMQ.
    Ответ написан
    2 комментария
  • Kubernetes: не получается добавить custom service-monitor?

    @MadridianFox
    Web-программист, многостаночник
    Prometheus-operator следит за созданием сервисмониторов в определённых неймспейсах, и фильтрует сервисмониторы по лейблам.
    Соответственно, вам необходимо посмотреть в манифесте прометеуса, какие значения там выставлены, и создать свой сервисмонитор с соответсвующем неймспейсе с необходимыми лейблами.
    Ответ написан
    2 комментария
  • Prometheus.yml файл не могу прописать правильно?

    karabanov
    @karabanov
    Системный администратор
    Читай логи docker-compose logs prometheus
    Ответ написан
    Комментировать
  • Kubernetes: не могу связать 2 pod-a вместе?

    Одним из вариантов исправления будут такие манифесты
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: http-http-deployment
      labels:
        app: http-http
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: http-http
      template:
        metadata:
          labels:
            app: http-http
        spec:
          containers:
            - name: http-http
              image: stasbigunenko/http_http
              env:
                - name: PORT_HTTP
                  value: ":8085"
                - name: GRPC
                  value: "grpc-service:9000"
              ports:
                - containerPort: 8085
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: http-grpc-deployment
      labels:
        app: http-grpc
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: http-grpc
      template:
        metadata:
          labels:
            app: http-grpc
        spec:
          containers:
            - name: http-grpc
              image: stasbigunenko/http_grpc
              env:
                - name: TCP_PORT
                  value: ":9000"
              ports:
                - containerPort: 9000
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: http-service
    spec:
      selector:
        app: http-http
      ports:
        - protocol: TCP
          port: 8085
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: grpc-service
    spec:
      selector:
        app: http-grpc
      ports:
        - protocol: TCP
          port: 9000
    Ответ написан
    3 комментария
  • Test in golang: simple function?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Как вариант можно что-то типа такого
    package main
    
    import "testing"
    
    func Test_sum(t *testing.T) {
    
        tt := []struct {
            args GetArgs
            sum int
        }{
            {Args {2, 4}, 6},
            {Args {2, -2}, 0},
        }
    
        for _, tc := range tt {
            tci := tc.args.(GetArgs)
            s := Sum(tci)
            if s != tc.sum {
                t.Errorf("sum of %v and %v should be %v, received- %v", tc.args.GetA(), tc.args.GetB(), tc.sum, s)
            }
        }
    }
    Ответ написан
    Комментировать
  • Gorilla Mux: не берет значение в vars := mux.Vars(r) Golang?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Через mux.Vars вы можете извлечь только то, что в URL, т.е. части URL, а параметры нужно извлекать через r.URL.Query().Get("param_name")

    Давайте разберём пример из реальной задачи.

    В URL содержится английское название категории (chairs), а также параметры фильтров width, height.
    https://domain.com/products/chairs?height=200&width=100


    Т.е. нужно отобразить все товары из категории "стулья" (chairs), но не выше 200 и не шире 100, соответственно нам нужно получить и chairs из URL и параметры.

    Роут будет таким в данном случае
    r.HandleFunc("/products/{category_handle}", h.ShowProducts).Methods("GET")


    А в обработчике будет уже вот так
    // из извлекаем из URL категорию
    vars := mux.Vars(r)
    categoryHandle := vars["categoryHandle"]
    
    // получаем параметры
    height, _ := strconv.Atoi(r.URL.Query().Get("height"))
    width, _ := strconv.Atoi(r.URL.Query().Get("width"))
    Ответ написан
    Комментировать
  • Работа с goroutines?

    EvgenyMamonov
    @EvgenyMamonov Куратор тега Go
    Senior software developer, system architect
    Есть несколько вариантов решения задачи
    передавать не указатель, а значение

    package main
    
    import (
      "fmt"
      "time"
    )
    
    var c = make(chan int, 3)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
      fmt.Println("Hello, playground")
      go save()
      go read()
      time.Sleep(3 * time.Second)
    }
    
    func save() {
      for _, val := range data {
        c <- val
      }
    }
    
    func read() {
      for {
        val := <-c
        fmt.Println("read:", val)
      }
    }

    скопировать значение и передать указатель на это значение

    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    var c = make(chan *int)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
    	fmt.Println("Hello, playground")
    	go save()
    	go read()
    	time.Sleep(3 * time.Second)
    }
    
    func save() {
    	for _, val := range data {
    	        v := val
    		c <- &v
    	}
    }
    
    func read() {
    	for {
    		val := <-c
    		fmt.Println("read:", *val)
    	}
    }

    передать правильный указатель, на элемент данных

    package main
    
    import (
    	"fmt"
    	"time"
    
    
    var c = make(chan *int, 5)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
    	fmt.Println("Hello, playground")
    	go save()
    	go read()
    	time.Sleep(3 * time.Second)
    }
    
    func save() {
    	for i := range data {
    		c <- &data[i]
    	}
    }
    
    func read() {
    	for {
    		val := <-c
    		fmt.Println("read:", *val)
    	}
    }



    Проблема в решении возникает потому, что вы передаёте один и тот же указатель при каждой итерации цикла, а когда вторая горутина читает - данные по этому указателю пишущая горутина уже пишет в этот участок памяти новые данные, именно по этой причине возникают одинаковые данные при выводе.

    Вот пример, который покажет, что адрес всегда один и тот же
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    var c = make(chan *int, 5)
    var data = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    func main() {
    	fmt.Println("Hello, playground")
    	go save()
    	go read()
    	time.Sleep(3 * time.Second)
    }
    
    func save() {
    	for _, val := range data {
    		c <- &val
    		fmt.Printf("write: %v\n", &val)
    	}
    }
    
    func read() {
    	for {
    		val := <-c
    		fmt.Println("read:", *val)
    	}
    }

    Вывод будет таким (адрес один и тот же)
    Hello, playground
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    write: 0xc000094000
    ...


    А в такой реализации (2й пример)
    func save() {
    	for _, val := range data {
    		v := val
    		c <- &v
    		fmt.Printf("write: %v\n", &v)
    	}
    }

    тут вывод будет таким (каждый раз новый участок памяти)
    Hello, playground
    write: 0xc000094000
    write: 0xc000094010
    write: 0xc000094018
    write: 0xc000094020
    write: 0xc000094028
    write: 0xc000094030

    В третьем варианте тоже будут разные указатели.
    Ответ написан
    5 комментариев