지속 시간에 정수를 곱하는 방법?


285

동시 고 루틴을 테스트하기 위해 함수에 한 줄을 추가하여 반환하는 데 임의의 시간이 걸립니다 (최대 1 초)

time.Sleep(rand.Int31n(1000) * time.Millisecond)

그러나 컴파일 할 때이 오류가 발생했습니다.

. \ crawler.go : 49 : 유효하지 않은 작업 : rand.Int31n (1000) * time.Millisecond (int32와 time.Duration이 일치하지 않는 유형)

어떤 아이디어? 지속 시간을 어떻게 곱할 수 있습니까?

답변:


431

int32그리고 time.Duration다른 유형입니다. 당신은 변환해야 int32A와 time.Duration같은 time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond).


5
고마워요. 나는 또한 난수 발생기 파종에 대해 배웠습니다rand.Seed(time.Now().Unix())
Panic

44
내 지식을 위해 다음은 어떻게 작동합니까? time.Sleep(time.Second * 2)
Ishan Khare

59
상수는 사용 방법에 따라 적응 형이 있기 때문에 작동합니다. 자세히 설명하는 Rob Pike의이 블로그 게시물을 참조하십시오. blog.golang.org/constants
mna

28
이것은 단순한 유형 시스템 (이 경우 연산자 과부하가 부족함)으로 인해 이상한 일 중 하나입니다. 실제로 더 의미가있는 원래 대신 Duration* Duration=로 곱셈을 캐스팅해야합니다 Duration. Duration* int= Duration.
Timmmm

14
연산자 오버로드 또는 암시 적 숫자 변환 으로이 작업을 수행 할 수 있습니다. 나는 암시 적 숫자 변환을 생략하는 것이 옳다고 생각합니다. int64(...) * Duration캐스트하는 것보다 훨씬 더 의미있는 이것에 대해 되돌아 보면 Duration, 이것은 유닛이 어떻게 작동 해야하는지에 대한 기본적인 위반입니다. 슬프게도 작동하지 않습니다. 정말 Duration * Duration끔찍한 일 을 해야합니다 .
Timmmm

60

올바른 형식으로 캐스트해야합니다 Playground.

yourTime := rand.Int31n(1000)
time.Sleep(time.Duration(yourTime) * time.Millisecond)

잠자기 문서를 확인 하는 경우 func Sleep(d Duration)지속 기간이 매개 변수로 필요하다는 것을 알 수 있습니다 . 귀하의 rand.Int31n의 반환 int32.

time.Sleep(100 * time.Millisecond)컴파일러가 여기에서 상수 100이 지속 시간을 의미한다는 것을 이해할 정도로 똑똑하기 때문에 예제의 줄이 작동합니다 ( ) . 그러나 변수를 전달하면 변수를 캐스트해야합니다.


16

Go에서는 동일한 유형의 변수를 곱할 수 있으므로 표현식의 두 부분이 모두 동일한 유형이어야합니다.

가장 간단한 방법은 곱하기 전에 정수를 지속 시간으로 캐스팅하는 것이지만 단위 의미를 위반합니다. 단위로 기간을 기간별로 곱하는 것은 무엇입니까?

차라리 time.Millisecond를 int64로 변환 한 다음 밀리 초 수를 곱한 다음 시간으로 캐스트합니다.

time.Duration(int64(time.Millisecond) * int64(rand.Int31n(1000)))

이런 식으로 표현의 어떤 부분도 그 유형에 따라 의미있는 가치를 가진다고 말할 수 있습니다. int64(time.Millisecond)부분은 차원이없는 값입니다. 원래 값에서 가장 작은 시간 단위 수입니다.

약간 더 간단한 길을 걷는 경우 :

time.Duration(rand.Int31n(1000)) * time.Millisecond

곱셈의 왼쪽 부분은 넌센스입니다. "time.Duration"유형의 값으로 해당 유형과 관련이없는 것을 보유합니다.

numberOfMilliseconds := 100
// just can't come up with a name for following:
someLHS := time.Duration(numberOfMilliseconds)
fmt.Println(someLHS)
fmt.Println(someLHS*time.Millisecond)

그리고 그것은 의미론뿐만 아니라 유형과 관련된 실제 기능이 있습니다. 이 코드는 다음을 인쇄합니다.

100ns
100ms

흥미롭게도 여기의 코드 샘플은 가장 간단한 코드를 사용하며 지속 기간 변환의 오해를 불러 일으키는 의미가 동일합니다 : https://golang.org/pkg/time/#Duration

초 : = 10

fmt.Print (time.Duration (seconds) * time.Second) // 10 초를 인쇄합니다


5

Go에는 Duration유형이 있습니다. 단위를 명시 적으로 정의하면 실제 문제를 예방할 수 있습니다.

또한 Go의 엄격한 유형 규칙으로 인해 Duration에 정수를 곱할 수 없습니다 . 일반적인 유형을 곱하려면 캐스트 를 사용해야합니다 .

/*
MultiplyDuration Hide semantically invalid duration math behind a function
*/
func MultiplyDuration(factor int64, d time.Duration) time.Duration {
    return time.Duration(factor) * d        // method 1 -- multiply in 'Duration'
 // return time.Duration(factor * int64(d)) // method 2 -- multiply in 'int64'
}

공식 문서는 방법 # 1을 사용하는 방법을 보여줍니다 :

정수 단위의 기간을 기간으로 변환하려면 다음을 곱하십시오.

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s

그러나 물론 지속 시간에 지속 시간을 곱하면 지속 시간이 생성되어서는 안됩니다. 예를 들어 5 밀리 초에 5 밀리 초를 곱하면 6h56m40s됩니다. 5 초를 제곱하려고하면 오버플로가 발생합니다 (상수로 수행하면 컴파일되지 않음).

그건 그렇고, 나노초 단위 의 int64표현은 "가장 큰 표현 가능 기간을 약 290 년으로 제한합니다." 는 이는 다음 과 같이 부호있는 값으로 취급 된다는 것을 나타냅니다 .DurationDurationint64(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

그래서 우리는 알고 있기 때문에의 기본 표현하는 것이 Duration이다 int64사이의 캐스트를 수행 int64하고 Duration합리적인 NO-OP입니다 - 유형을 혼합에 대한 언어 규칙을 만족하는 경우에만 필요하며 이후의 곱셈 연산에 영향을주지 않습니다.

순도 때문에 주조를 좋아하지 않으면 위에 표시된 것처럼 함수 호출에 묻습니다.


" 공통 유형 으로 / 함께 곱하기 ".
nobar

여기 에서 (잘못된) 답변의 부서와 관련된 비슷한 토론이 있습니다 .
nobar

-3

변수를 시간에 곱하기 위해 다음 코드를 사용하여 두 번째

    oneHr:=3600
    addOneHrDuration :=time.Duration(oneHr)
    addOneHrCurrTime := time.Now().Add(addOneHrDuration*time.Second)

이것은 Go의 time.Duration변수 를 사용하는 좋은 방법이 아닙니다 . addOneHrDuration시간 변수 의 이름을 지정한 time.Duration다음 1 시간이 아닌 3600ns로 설정하십시오. A의 time.Duration기본 단위는 나노초입니다. 실제로 1 시간 동안 작업하려면 const oneHourDuration = 60 * time.Hour(또는 3600 * time.Second또는 time.Hour) 와 같은 작업을 수행 할 수 있습니다.
Dave C
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.