똑같은 삽질은 2번 하지 말자

Golang vol.5 본문

Go

Golang vol.5

곽빵 2022. 5. 5. 12:57

개요

고랭 학습하면서 느낀점이나 기록하면 좋을법한 내용들을 정리

 

1. Go Routine

고루틴은 Go 런타임이 관리하는 논리적 쓰레드이다. 함수를 호출할 때 앞에 'go'라는 키워드를 붙여서 호출하면 호출하는 함수와 현재 실행하고 있는 함수의 흐름이 구분되어 별개로 동작한다. 'go' 키워드를 붙여서 호출한 함수는 동시성을 가진다고 할 수 있으며 고루틴끼리의 의존 관계가 없으므로 고루틴 함수의 실행 순서는 프로그램에 영향을 미치지 않는다. 

 

시간이 많이 걸리는 작업은 밑과 같이 go 키워드를 붙여서 비동기로써 실행하면 더욱 효울적인 처리가 가능해진다.

func UpdateProduct(c *fiber.Ctx) error {
	...생략

	database.DB.Model(&product).Updates(&product) // 상품 업데이트

	// 상품이 업데이트 되었음으로 상품리스트가 있는 캐시를 비워준다.
	go deleteCache("products_frontend") // 비동기처리
	go func(key string) {               // 이렇게 익명함수로도 go 키워드를 사용할 수 있다.
		time.Sleep(5 * time.Second)
		database.Cache.Del(context.Background(), key)
	}("products_backend")

	return c.JSON(product)
}

func deleteCache(key string) {
	time.Sleep(5 * time.Second) // 이 작업이 5초가 걸린다고 가정
	database.Cache.Del(context.Background(), key)
}

 

2. Channel

채널은 데이터를 주고 받는 통로 역할을 하는 자료구조이다. 채널에 데이터를 넣고 뽑아내는 형태로 사용하며 흔히 서로 다른 고루틴 사이에 통신을 위해 쓰인다. Go는 채널을 기본 자료형으로 제공한다. 따라서 다른 패키지나 라이브러리 없이 바로 사용할 수 있다.

 

고루틴과 채널의 조합을 활용해보자

CacheChannel을 chan string으로써 정의한다.

CacheChannel = make(chan string)으로 채널을 만들고 수신을 대기

채널에 값이 들어오면 ClearCache를 함으로써 캐시를 비운다.

(javascript의 이벤트 리스너같은 느낌이다.)

var (
	Cache        *redis.Client
	CacheChannel chan string
)

func SetupRedis() {
	Cache = redis.NewClient(&redis.Options{
		Addr: "redis:6379",
	})
}

func SetupCacheChannel() {
	CacheChannel = make(chan string) // 수신자

	go func(ch chan string) {
		for {
			temp := <-ch // 채널에 들어온 값을 빼낸다
			time.Sleep(5 * time.Second)

			Cache.Del(context.Background(), temp)

			fmt.Println("Cache Clear", temp)
		}
	}(CacheChannel)
}

func ClearCache(keys ...string) { // 송신자
	for _, key := range keys {
		CacheChannel <- key // key값을 채널에 넣는다
	}
}

 

채널에 데이터를 전송하기 위해서 송신자를 실행시킨다.

go database.ClearCache("products_frontend", "products_backend")

 

3. Sorted Set, ZAdd

Redis에서 순서를 가지는 집합의 자료구조가 필요할 때 go에서 만드는 방법

package main

import (
	"context"

	"ambassador/src/database"
	"ambassador/src/models"

	"github.com/go-redis/redis/v8"
)

func main() {
	database.Connect()
	database.SetupRedis()

	ctx := context.Background()

	var users []models.User

	database.DB.Find(&users, models.User{
		IsAmbassador: true,
	})

	for _, user := range users {
		ambassador := models.Ambassador(user)
		ambassador.CalculateRevenue(database.DB)

		database.Cache.ZAdd(ctx, "rankings", &redis.Z{
			Score:  *ambassador.Revenue,
			Member: user.GetName(),
		})

	}
}

 

4. Go에서 Stripe

go get -u github.com/stripe/stripe-go/v72

https://github.com/stripe/stripe-go

 

GitHub - stripe/stripe-go: Go library for the Stripe API.

Go library for the Stripe API. . Contribute to stripe/stripe-go development by creating an account on GitHub.

github.com

 

그리고 stripe 사이트에 들어가서 회원가입 후 테스트로 이용해 볼 수 있다.

 

(그전에 에러가 한번 났었는데 이하의 Account Name을 셋팅안하면 테스트 API도 이용할 수 없는 모양이다.)

 

Usage


import (
	...

	"github.com/stripe/stripe-go/v72"
	"github.com/stripe/stripe-go/v72/checkout/session"
)

func CreateOrder(c *fiber.Ctx) error {
	...
    
	tx := database.DB.Begin()

	// Stripe Payment Start
	stripe.Key = "sk_test_51KvyLfCXj5HN8X9OG0WQD9JH5Apwz7LFQjvIYeG8eMCnUS1bA6UUhMZtIiwebnnCHAhIx2rLJtthjJlOwQ3sLKam00FnCljC4r"
    
	params := stripe.CheckoutSessionParams{
		SuccessURL:         stripe.String("http://localhost:5000/success?source={CHECKOUT_SESSION_ID}"),
		CancelURL:          stripe.String("http://localhost:5000/error"),
		PaymentMethodTypes: stripe.StringSlice([]string{"card"}),
		LineItems:          lineItems, // 상품정보들 []{ Name Description Images Amount Currency Quantity }
	}

	source, err := session.New(&params)
	if err != nil {
		tx.Rollback()
		c.Status(fiber.StatusBadRequest)
		return c.JSON(fiber.Map{
			"message": err.Error(),
		})
	}
	order.TransactionId = source.ID
	if err := tx.Save(&order).Error; err != nil {
		tx.Rollback()
		c.Status(fiber.StatusBadRequest)
		return c.JSON(fiber.Map{
			"message": err.Error(),
		})
	}
	// Stripe Payment Over

	tx.Commit()

	return c.JSON(order)
}

'Go' 카테고리의 다른 글

Golang vol.3  (0) 2022.04.25
Golang vol.1 (Getting Start, := = 차이, 함수)  (0) 2022.04.17
Comments