Оптимизация кода golang

Когда мы фильтруем фрагменты в Go, типичным решением является создание нового фрагмента для отфильтрованных элементов (var filtered []int).

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

Более разумным способом решения этой проблемы является такое создание filtered := numbers[:0]

Так мы создадим слайс с ёмкостью numbers и избегаем дополнительных выделений памяти в дальнейшем

В выражении numbers[:0], 0 указывает на индекс, до которого (не включая его) будут скопированы элементы из среза numbers. По сути, это создает новый срез, который имеет ту же емкость, что и исходный срез numbers, но не содержит никаких элементов.

Вот как это работает:

  • numbers[:] создает копию среза numbers, включая все его элементы.
  • numbers[:n], где n — это неотрицательное целое число, создает новый срез, который содержит первые n элементов numbers.
  • numbers[:0] создает новый срез, который не содержит элементов, но имеет ту же емкость, что и numbers. Это означает, что при добавлении элементов в срез filtered с помощью функции append память будет выделена из исходного массива, который лежит в основе среза numbers, до тех пор, пока не будет превышена его емкость.

Проблема XY (Ошибка молотка)

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

Проблема XY обычно встречается в среде технической поддержки или обслуживания клиентов, где конечный пользователь пытается решить проблему самостоятельно и неправильно понимает реальную природу проблемы, полагая, что их реальная проблема X уже решена, за исключением некоторых мелких деталей Y в их решении. Неспособность обслуживающего персонала решить реальную проблему или понять природу запроса может привести к разочарованию конечного пользователя. Ситуация может проясниться, если конечный пользователь спросит о какой-то «бессмысленной» детали, которая не связана с полезной конечной целью. Решение для обслуживающего персонала состоит в том, чтобы задавать наводящие вопросы: зачем нужна эта информация, чтобы выявить корень проблемы и перенаправить конечного пользователя с непродуктивного пути исследования.

Fixing For Loops in Go 1.22

Fixing For Loops in Go 1.22

https://go.dev/blog/loopvar-preview

David Chase и Russ Cox в официальном блоге Go рассказывают про проблему LoopVar (переменной цикла) и приводят конкретные примеры, в том числе из реального кейса проекта — Lets Encrypt.

Затем рассказывают, как именно эта проблема решается. Если кратко:

> change for loops to make these variables have per-iteration scope instead of per-loop scope

Как вы помните, эта фича уже есть в Go v1.21, но её нужно включить:

GOEXPERIMENT=loopvar go test

А в версии 1.22 она уже будет работать по-умолчанию

Log Requests and Responses in Gin!



package main

import "github.com/gin-gonic/gin"


func RequestLogger() gin.HandlerFunc {
    return func(c *gin.Context) {
        t := time.Now()

        c.Next()

        latency := time.Since(t)

        fmt.Printf("%s %s %s %s\n",
            c.Request.Method,
            c.Request.RequestURI,
            c.Request.Proto,
            latency,
        )
    }
}

func ResponseLogger() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Writer.Header().Set("X-Content-Type-Options", "nosniff")

        c.Next()

        fmt.Printf("%d %s %s\n",
            c.Writer.Status(),
            c.Request.Method,
            c.Request.RequestURI,
        )
    }
}

func main() {
    r := gin.Default()
    // Add logging middleware
    r.Use(RequestLogger())
    r.Use(ResponseLogger())

    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "Hello, World!",
        })
    })

    r.Run() // listen and serve on 0.0.0.0:8080
}



Получить курс доллара на forex


func forex() string {
	client := &http.Client{
		Timeout: 10 * time.Second,  
	}

 	req, err := http.NewRequest("GET", "https://www.investing.com/currencies/usd-rub", nil)
	if err != nil {
		log.Fatal(err)
	}

 	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537")

	res, err := client.Do(req)
	if err != nil {
		log.Println(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		log.Printf("status code error: %d %s", res.StatusCode, res.Status)
	}

	// Load the HTML document
	doc, err := goquery.NewDocumentFromReader(res.Body)
	if err != nil {
		log.Println(err)
	}

	var price string
	doc.Find("span[data-test='instrument-price-last']").Each(func(index int, item *goquery.Selection) {
		price = item.Text()
		fmt.Println(price)
	})

	return price
}