LEFT | RIGHT |
(no file at all) | |
1 <!--{ | 1 <!--{ |
2 "Title": "Effective Go", | 2 "Title": "Effective Go", |
3 "Template": true | 3 "Template": true |
4 }--> | 4 }--> |
5 | 5 |
6 <h2 id="introduction">Introduction</h2> | 6 <h2 id="introduction">Introduction</h2> |
7 | 7 |
8 <p> | 8 <p> |
9 Go is a new language. Although it borrows ideas from | 9 Go is a new language. Although it borrows ideas from |
10 existing languages, | 10 existing languages, |
(...skipping 2924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2935 Receivers always block until there is data to receive. | 2935 Receivers always block until there is data to receive. |
2936 If the channel is unbuffered, the sender blocks until the receiver has | 2936 If the channel is unbuffered, the sender blocks until the receiver has |
2937 received the value. | 2937 received the value. |
2938 If the channel has a buffer, the sender blocks only until the | 2938 If the channel has a buffer, the sender blocks only until the |
2939 value has been copied to the buffer; if the buffer is full, this | 2939 value has been copied to the buffer; if the buffer is full, this |
2940 means waiting until some receiver has retrieved a value. | 2940 means waiting until some receiver has retrieved a value. |
2941 </p> | 2941 </p> |
2942 <p> | 2942 <p> |
2943 A buffered channel can be used like a semaphore, for instance to | 2943 A buffered channel can be used like a semaphore, for instance to |
2944 limit throughput. In this example, incoming requests are passed | 2944 limit throughput. In this example, incoming requests are passed |
2945 to <code>handle</code>, which receives a value from the channel, processes | 2945 to <code>handle</code>, which sends a value into the channel, processes |
2946 the request, and then sends a value back to the channel | 2946 the request, and then receives a value from the channel |
2947 to ready the "semaphore" for the next consumer. | 2947 to ready the “semaphore” for the next consumer. |
2948 The capacity of the channel buffer limits the number of | 2948 The capacity of the channel buffer limits the number of |
2949 simultaneous calls to <code>process</code>, | 2949 simultaneous calls to <code>process</code>. |
2950 so during initialization we prime the channel by filling it to capacity. | |
2951 </p> | 2950 </p> |
2952 <pre> | 2951 <pre> |
2953 var sem = make(chan int, MaxOutstanding) | 2952 var sem = make(chan int, MaxOutstanding) |
2954 | 2953 |
2955 func handle(r *Request) { | 2954 func handle(r *Request) { |
2956 <-sem // Wait for active queue to drain. | 2955 sem <- 1 // Wait for active queue to drain. |
2957 process(r) // May take a long time. | 2956 process(r) // May take a long time. |
2958 sem <- 1 // Done; enable next request to run. | 2957 <-sem // Done; enable next request to run. |
2959 } | |
2960 | |
2961 func init() { | |
2962 for i := 0; i < MaxOutstanding; i++ { | |
2963 sem <- 1 | |
2964 } | |
2965 } | 2958 } |
2966 | 2959 |
2967 func Serve(queue chan *Request) { | 2960 func Serve(queue chan *Request) { |
2968 for { | 2961 for { |
2969 req := <-queue | 2962 req := <-queue |
2970 go handle(req) // Don't wait for handle to finish. | 2963 go handle(req) // Don't wait for handle to finish. |
2971 } | 2964 } |
2972 } | 2965 } |
2973 </pre> | 2966 </pre> |
2974 | 2967 |
2975 <p> | 2968 <p> |
2976 Because data synchronization occurs on a receive from a channel | 2969 Once <code>MaxOutstanding</code> handlers are executing <code>process</code>, |
2977 (that is, the send "happens before" the receive; see | 2970 any more will block trying to send into the filled channel buffer, |
2978 <a href="/ref/mem">The Go Memory Model</a>), | 2971 until one of the existing handlers finishes and receives from the buffer. |
2979 acquisition of the semaphore must be on a channel receive, not a send. | |
2980 </p> | 2972 </p> |
2981 | 2973 |
2982 <p> | 2974 <p> |
2983 This design has a problem, though: <code>Serve</code> | 2975 This design has a problem, though: <code>Serve</code> |
2984 creates a new goroutine for | 2976 creates a new goroutine for |
2985 every incoming request, even though only <code>MaxOutstanding</code> | 2977 every incoming request, even though only <code>MaxOutstanding</code> |
2986 of them can run at any moment. | 2978 of them can run at any moment. |
2987 As a result, the program can consume unlimited resources if the requests come in
too fast. | 2979 As a result, the program can consume unlimited resources if the requests come in
too fast. |
2988 We can address that deficiency by changing <code>Serve</code> to | 2980 We can address that deficiency by changing <code>Serve</code> to |
2989 gate the creation of the goroutines. | 2981 gate the creation of the goroutines. |
2990 Here's an obvious solution, but beware it has a bug we'll fix subsequently: | 2982 Here's an obvious solution, but beware it has a bug we'll fix subsequently: |
2991 </p> | 2983 </p> |
2992 | 2984 |
2993 <pre> | 2985 <pre> |
2994 func Serve(queue chan *Request) { | 2986 func Serve(queue chan *Request) { |
2995 for req := range queue { | 2987 for req := range queue { |
2996 <-sem | 2988 sem <- 1 |
2997 go func() { | 2989 go func() { |
2998 process(req) // Buggy; see explanation below. | 2990 process(req) // Buggy; see explanation below. |
2999 sem <- 1 | 2991 <-sem |
3000 }() | 2992 }() |
3001 } | 2993 } |
3002 }</pre> | 2994 }</pre> |
3003 | 2995 |
3004 <p> | 2996 <p> |
3005 The bug is that in a Go <code>for</code> loop, the loop variable | 2997 The bug is that in a Go <code>for</code> loop, the loop variable |
3006 is reused for each iteration, so the <code>req</code> | 2998 is reused for each iteration, so the <code>req</code> |
3007 variable is shared across all goroutines. | 2999 variable is shared across all goroutines. |
3008 That's not what we want. | 3000 That's not what we want. |
3009 We need to make sure that <code>req</code> is unique for each goroutine. | 3001 We need to make sure that <code>req</code> is unique for each goroutine. |
3010 Here's one way to do that, passing the value of <code>req</code> as an argument | 3002 Here's one way to do that, passing the value of <code>req</code> as an argument |
3011 to the closure in the goroutine: | 3003 to the closure in the goroutine: |
3012 </p> | 3004 </p> |
3013 | 3005 |
3014 <pre> | 3006 <pre> |
3015 func Serve(queue chan *Request) { | 3007 func Serve(queue chan *Request) { |
3016 for req := range queue { | 3008 for req := range queue { |
3017 <-sem | 3009 sem <- 1 |
3018 go func(req *Request) { | 3010 go func(req *Request) { |
3019 process(req) | 3011 process(req) |
3020 sem <- 1 | 3012 <-sem |
3021 }(req) | 3013 }(req) |
3022 } | 3014 } |
3023 }</pre> | 3015 }</pre> |
3024 | 3016 |
3025 <p> | 3017 <p> |
3026 Compare this version with the previous to see the difference in how | 3018 Compare this version with the previous to see the difference in how |
3027 the closure is declared and run. | 3019 the closure is declared and run. |
3028 Another solution is just to create a new variable with the same | 3020 Another solution is just to create a new variable with the same |
3029 name, as in this example: | 3021 name, as in this example: |
3030 </p> | 3022 </p> |
3031 | 3023 |
3032 <pre> | 3024 <pre> |
3033 func Serve(queue chan *Request) { | 3025 func Serve(queue chan *Request) { |
3034 for req := range queue { | 3026 for req := range queue { |
3035 <-sem | |
3036 req := req // Create new instance of req for the goroutine. | 3027 req := req // Create new instance of req for the goroutine. |
| 3028 sem <- 1 |
3037 go func() { | 3029 go func() { |
3038 process(req) | 3030 process(req) |
3039 sem <- 1 | 3031 <-sem |
3040 }() | 3032 }() |
3041 } | 3033 } |
3042 }</pre> | 3034 }</pre> |
3043 | 3035 |
3044 <p> | 3036 <p> |
3045 It may seem odd to write | 3037 It may seem odd to write |
3046 </p> | 3038 </p> |
3047 | 3039 |
3048 <pre> | 3040 <pre> |
3049 req := req | 3041 req := req |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3637 <pre> | 3629 <pre> |
3638 verifying implementation | 3630 verifying implementation |
3639 type Color uint32 | 3631 type Color uint32 |
3640 | 3632 |
3641 // Check that Color implements image.Color and image.Image | 3633 // Check that Color implements image.Color and image.Image |
3642 var _ image.Color = Black | 3634 var _ image.Color = Black |
3643 var _ image.Image = Black | 3635 var _ image.Image = Black |
3644 </pre> | 3636 </pre> |
3645 --> | 3637 --> |
3646 | 3638 |
LEFT | RIGHT |