반응형

Go memory 사용량 확인

var memStats runtime.MemStats
runtime.ReadMemStats(&memStats)
initialMemoryUsage := memStats.TotalAlloc

runtime.ReadMemStats(&memStats)
finalMemoryUsage := memStats.TotalAlloc
memoryUsed := finalMemoryUsage - initialMemoryUsage
fmt.Printf("총 메모리 사용량: %d bytes\n", memoryUsed)
반응형

'Golang > Let's Go' 카테고리의 다른 글

Go 1.21에서 추가된 slice 의 기능  (0) 2023.11.04
Go function? Go Method?  (0) 2023.10.12
BindJSON vs ShouldBindJSON  (0) 2023.10.12
Go 변수와 상수  (0) 2023.10.01
Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
반응형

Go 1.21에서 추가된 slice 의 기능

 

Contains

ex 슬라이스에 value 가 있는지 확인하고, 존재하면 true 를 반환한다.

//추가된 기능
ex := []string{"A", "B", "C"}
ok := slices.Contains(ex, "B")
fmt.Sprintf("%t", ok) // true

//이전 기능
func contains(slice []string, key string) bool {
	ex := make(map[string]struct{}, len(slice))
	for _, s := range slice {
    	ex[s] = struct{}{}
	}
	_, ok := m[key]
return ok
}

 

Insert

ex 슬라이스 내의 i 위치에 value 를 추가하고 반환한다.

//추가된 기능
ex := []string{"A", "B", "C"}
ex = slices.Insert(ex, len(ex), "D")
fmt.Sprintf("%v", ex) // [A B C D]

//이전 기능
ex := []string{"A", "B", "C"}
m = append(ex, "D")
fmt.Sprintf("%v", m) //[A B C D]

 

Delete

ex 슬라이스 내에 있는 요소를 i 에서 j 위치까지 삭제하고 반환한다.

 

//추가된 기능
//ex[A B C D]
ex = slices.Delete(ex, len(ex)-1, len(ex))
fmt.Sprintf("%v", ex) // [A B C]

//이전 기능
ex = append(ex[:len(ex)-1], ex[len(ex):]...)
fmt.Sprintf("%v", ex) // [A B C]

 

반응형

'Golang > Let's Go' 카테고리의 다른 글

Go memory 사용량 확인  (0) 2023.12.13
Go function? Go Method?  (0) 2023.10.12
BindJSON vs ShouldBindJSON  (0) 2023.10.12
Go 변수와 상수  (0) 2023.10.01
Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
반응형

Go function? Go Method?

Go 에서 function 을 만들거나 Method 를 만들 때, 이게 Go 에서 function 인지 Method 인지 헷갈려서 글을 올립니다.

Go 에서는 보통 개발자가 알고 있는 function 이 function 이고, 구조체에 추가한 동작을 Method 라고 합니다.

반응형

'Golang > Let's Go' 카테고리의 다른 글

Go memory 사용량 확인  (0) 2023.12.13
Go 1.21에서 추가된 slice 의 기능  (0) 2023.11.04
BindJSON vs ShouldBindJSON  (0) 2023.10.12
Go 변수와 상수  (0) 2023.10.01
Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
반응형

BindJSON vs ShouldBindJSON

BindJSON 은 확인해보면 *http.Request 를 사용하는 것을 확인할 수 있습니다. 그렇기 때문에 error 가 발생할 때 Request status code 가 400으로 변경되고 content-type 이 text/plain; charset=utf-8 로 변경됩니다. 이러한 점 때문에 ShouldBindJSON 사용을 권장하기도 합니다.

근데 테스트나 글 찾아보면 ShouldBindJSON 은 http.request 를 건들지 않는다고 하는데, Binding interface 까지 가보면 결국 BindJSON 과 같이 *Context.Request 를 호출해서 사용하는 걸 확인할 수 있습니다.

정확하게 문제에 대해서 이야기 한 사람 내용 입니다.

[이슈 설명] 현재, 함수 ctx.Bind, ctx.BindJSON, ctx.BindQuery는 모두 ctx.MustBindWith를 사용합니다. 제 의견으로는 현재의 ctx.MustBindWith의 구현에는 다음과 같은 단점이 있습니다. 이것은 이미 이전에 논의되었으며 여러 문제와 스레드를 크롤링하지 않기 위해 여기에 포함시킴을 양해 부탁드립니다.

  1. 제어 부족
    • HTTP 상태 코드를 400으로 설정하며 개발자는 다른 HTTP 상태 코드(ex: 422, http.StatusUnprocessableEntity)를 설정할 수 없습니다.
    • 이것은 핸들러 체인을 중단합니다. 개발자는 결과 오류를 중단할 가치가 있는지 또는 조화될 수 있는지 결정할 수 있어야 합니다.
    • Bind JSON 및 Query에서 논의한대로 반복된 Bind를 사용할 수 없습니다. 개발자는 쿼리 매개변수와 JSON 본문을 별도로 바인딩하고 싶을 수 있습니다.
  2. 가능한 잘못된 Content-type 헤더
    • Content-type을 text/plain으로 설정합니다.
    • ctx.JSON 또는 수동으로 콘텐츠 유형 헤더를 설정하려 해도 도움이 되지 않습니다. 대신 다음과 같은 경고가 표시됩니다: [GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422

[제안] 역호환성을 유지하기 위해 기존 바인드 방법의 동작을 변경할 수 없습니다. 따라서 이 PR은 ShouldBind 대응 항목을 추가합니다 - ctx.ShouldBind, ctx.ShouldBindJSON, ctx.ShouldBindQuery.

Readme 파일은 아직 업데이트하지 않았으며 여기서의 토론 결과에 따라 업데이트할 것을 제안합니다. readme의 모든 예제를 Should 동등 항목을 사용하도록 전환하는 것을 제안합니다. readme에 있는 모든 예제는 ShouldBind 방법을 사용하도록 업데이트되었습니다. 또한 Bind와 ShouldBind 방법의 차이를 설명하는 섹션을 추가했습니다.

참조

반응형

'Golang > Let's Go' 카테고리의 다른 글

Go 1.21에서 추가된 slice 의 기능  (0) 2023.11.04
Go function? Go Method?  (0) 2023.10.12
Go 변수와 상수  (0) 2023.10.01
Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
Golang 속도 측정 방법  (0) 2023.08.28
반응형

Go 변수와 상수

상수는 Go 키워드 const 를 사용하여 선언합니다.

const c int = 10

const (
	v = "Vista"
	ma = "Master"
	a = "Amend"
)

//상수값을 0부터 순차적으로 부여하기 위해 iota 라는 identifier 를 사용할 수 있습니다.

const (
	v = iota //0
	ma //1
	a //2
)

 

Go 키워드로는 break, default, func, interface, select, case, ... 가 있습니다.

//특정 case 의 문장을 실행한 뒤 다음 case 의 문장을 실행하고 싶을 때는 fallthrough 키워드를 사용합니다.
//단, 맨 마지막 case 에는 fallthrough 키워드를 사용할 수 없습니다.
fallthrough
i := 3

switch i { //값을 판단할 변수 설정
case 4: //각 조건에 일치하는
	fmt.Println("4 이상") //코드를 실행합니다.
	fallthrough
case 3: // 3과 변수의 값이 일치하므로
	fmt.Println("3 이상") //이 부분을 실행
	fallthrough //fallthrough를 사용했으므로 아래 case를 모두 실행
case 2:
	fmt.Println("2 이상") //실행
	fallthrough
case 1:
	fmt.Println("1 이상") //실행
	fallthrough
case 0:
	fmt.Println("0 이상") //실행, 마지막 case에는 fallthrough를 사용할 수 없음
}
반응형

'Golang > Let's Go' 카테고리의 다른 글

Go function? Go Method?  (0) 2023.10.12
BindJSON vs ShouldBindJSON  (0) 2023.10.12
Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
Golang 속도 측정 방법  (0) 2023.08.28
Go smtp SendMail 기능 구현(기본 구현과 개선)  (0) 2023.08.24
반응형

Go 에러로 인한 서버 다운 막는 방법

golang은 에러가 발생하면 서버가 다운됩니다. 서버 다운을 막기 위해 try-catch가 있으면 좋지만 golang은 없기 때문에 다른 방법을 찾아봤습니다.

해결 방안으로는 defer 와 panic + recover를 사용했습니다.

 

 

코드

func test() {
	client, err := db.Open("", "")
	
	defer func() {
		client.Close()
		if r := recover(); r != nil {
			//에러 처리
		}
	}()
	
	if err != nil {
		panic(err)
	}
}
반응형

'Golang > Let's Go' 카테고리의 다른 글

BindJSON vs ShouldBindJSON  (0) 2023.10.12
Go 변수와 상수  (0) 2023.10.01
Golang 속도 측정 방법  (0) 2023.08.28
Go smtp SendMail 기능 구현(기본 구현과 개선)  (0) 2023.08.24
Zero allocation  (0) 2023.08.10
반응형

Golang 속도 측정 방법

 

코드

startTime := time.Now()

elapsedTime := time.Since(startTime)
fmt.Printf("실행시간: %s\n", elapsedTime)
반응형

'Golang > Let's Go' 카테고리의 다른 글

Go 변수와 상수  (0) 2023.10.01
Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
Go smtp SendMail 기능 구현(기본 구현과 개선)  (0) 2023.08.24
Zero allocation  (0) 2023.08.10
Go 패키지 외부 공개 여부  (0) 2023.08.09
반응형

Go smtp SendMail 기능 구현

 

사용한 메일 서버

- gmail 서버

 

사용한 라이브러리

- "net/smtp"

 

구현할 때 주의할 점

- 메일 여러개를(현재 테스트 해봤을 때는 10개까지) 보냈을 때 gmail 서버에서 스팸으로 인식해서 걸러버리기 때문에 발송하는 메세지 부분에서 특정 값들을 넣어 스팸으로 인식하지 못하도록 해야합니다.

 

 

구현

import (
	"net/smtp"
)

func SendMail() {
    auth := smtp.PlainAuth("", "", "", "smtp.gmail.com")
    from := ""
    to := []string{""}

    // 메시지 작성
    headerSubject := "Subject: [제목] 메일 테스트 발송입니다\r\n"
    headerBlank := "\r\n"
    body := "[본문] 메일 테스트 발송"
    msg := []byte(headerSubject + headerBlank + body)

    // 메일 보내기
    err := smtp.SendMail("smtp.gmail.com:587", auth, from, to, msg)
    if err != nil {
        log.Fatalf("Failed to send the email: %v", err)
    }
    
    return
}

 

기본 구현의 문제점

- 여러 메일을 한 번에 보내도록 for문을 작성하여 구현하면 스팸으로 인식하는 문제와 처리 속도가 느려진다는 문제가 있습니다. 1개의 메일을 처리하고 return 하는데 2초 이상이 걸립니다. 만약 10개 이상이면 20초가 아닌 더 오래 걸립니다.

 

 

개선

func SendMail() {
	auth := smtp.PlainAuth("", sms.GetEmailInfo(), sms.GetEmailPasswordInfo(), sms.GetEmailHostInfo())
	from := sms.GetEmailInfo()
	to := []string{sms.GetEmailInfo()} // 아직 따로 DB에서 데이터를 가져올 것이 없어 개발자 메일을 가져왔습니다.

	// 메시지 작성
	headerSubject := "Subject: [제목] 메일 테스트 발송입니다\r\n"
	headerBlank := "\r\n"
	body := "[본문] 메일 테스트 발송"
	//msg := []byte(headerSubject + headerBlank + body)

	// 메일 보내기
	var wg sync.WaitGroup
	for _, t := range to {
		wg.Add(1)
		go func(t string) {
			defer wg.Done()
			go smtp.SendMail("smtp.gmail.com:587", auth, from, to, []byte(fmt.Sprintf(headerSubject+headerBlank+body, t)))
		}(t)
	}

	wg.Wait()
}

 

개선 사항

- go의 장점인 go routine을 사용하여 비동기 방식으로 코드를 짜서 smtp.SendMail() 함수가 끝날 때까지 매번 기달리지 않고 for문을 돌고 SendMail() 함수를 끝냅니다. 기존에 걸리던 2초를 밀리세컨드로 줄였고, 대량으로 메일을 보내도 함수 실행에서 종료까지의 속도는 밀리세컨드로 유지됩니다.

반응형

'Golang > Let's Go' 카테고리의 다른 글

Go 에러로 인한 서버 다운 막는 방법  (0) 2023.08.28
Golang 속도 측정 방법  (0) 2023.08.28
Zero allocation  (0) 2023.08.10
Go 패키지 외부 공개 여부  (0) 2023.08.09
go work 실행 함수  (0) 2023.08.09

+ Recent posts