Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 <!-- Effective Go --> | 1 <!-- Effective Go --> |
2 | 2 |
3 <h2 id="introduction">Introduction</h2> | 3 <h2 id="introduction">Introduction</h2> |
4 | 4 |
5 <p> | 5 <p> |
6 Go is a new language. Although it borrows ideas from | 6 Go is a new language. Although it borrows ideas from |
7 existing languages, | 7 existing languages, |
8 it has unusual properties that make effective Go programs | 8 it has unusual properties that make effective Go programs |
9 different in character from programs written in its relatives. | 9 different in character from programs written in its relatives. |
10 A straightforward translation of a C++ or Java program into Go | 10 A straightforward translation of a C++ or Java program into Go |
(...skipping 1860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1871 set up. Here's a trivial but complete implementation of a handler to | 1871 set up. Here's a trivial but complete implementation of a handler to |
1872 count the number of times the | 1872 count the number of times the |
1873 page is visited. | 1873 page is visited. |
1874 </p> | 1874 </p> |
1875 <pre> | 1875 <pre> |
1876 // Simple counter server. | 1876 // Simple counter server. |
1877 type Counter struct { | 1877 type Counter struct { |
1878 n int | 1878 n int |
1879 } | 1879 } |
1880 | 1880 |
1881 func (ctr *Counter) ServeHTTP(c http.ResponseWriter, req *http.Request) { | 1881 func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
rsc1
2010/09/29 18:02:58
Probably change all the c to w.
| |
1882 ctr.n++ | 1882 ctr.n++ |
1883 fmt.Fprintf(c, "counter = %d\n", ctr.n) | 1883 fmt.Fprintf(w, "counter = %d\n", ctr.n) |
1884 } | 1884 } |
1885 </pre> | 1885 </pre> |
1886 <p> | 1886 <p> |
1887 (Keeping with our theme, note how <code>Fprintf</code> can print to an HTTP conn ection.) | 1887 (Keeping with our theme, note how <code>Fprintf</code> can print to an |
rsc1
2010/09/29 18:02:58
to a ResponseWriter.
| |
1888 <code>http.ResponseWriter</code>.) | |
1888 For reference, here's how to attach such a server to a node on the URL tree. | 1889 For reference, here's how to attach such a server to a node on the URL tree. |
1889 <pre> | 1890 <pre> |
1890 import "http" | 1891 import "http" |
1891 ... | 1892 ... |
1892 ctr := new(Counter) | 1893 ctr := new(Counter) |
1893 http.Handle("/counter", ctr) | 1894 http.Handle("/counter", ctr) |
1894 </pre> | 1895 </pre> |
1895 <p> | 1896 <p> |
1896 But why make <code>Counter</code> a struct? An integer is all that's needed. | 1897 But why make <code>Counter</code> a struct? An integer is all that's needed. |
1897 (The receiver needs to be a pointer so the increment is visible to the caller.) | 1898 (The receiver needs to be a pointer so the increment is visible to the caller.) |
1898 </p> | 1899 </p> |
1899 <pre> | 1900 <pre> |
1900 // Simpler counter server. | 1901 // Simpler counter server. |
1901 type Counter int | 1902 type Counter int |
1902 | 1903 |
1903 func (ctr *Counter) ServeHTTP(c http.ResponseWriter, req *http.Request) { | 1904 func (ctr *Counter) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
1904 *ctr++ | 1905 *ctr++ |
1905 fmt.Fprintf(c, "counter = %d\n", *ctr) | 1906 fmt.Fprintf(w, "counter = %d\n", *ctr) |
1906 } | 1907 } |
1907 </pre> | 1908 </pre> |
1908 <p> | 1909 <p> |
1909 What if your program has some internal state that needs to be notified that a pa ge | 1910 What if your program has some internal state that needs to be notified that a pa ge |
1910 has been visited? Tie a channel to the web page. | 1911 has been visited? Tie a channel to the web page. |
1911 </p> | 1912 </p> |
1912 <pre> | 1913 <pre> |
1913 // A channel that sends a notification on each visit. | 1914 // A channel that sends a notification on each visit. |
1914 // (Probably want the channel to be buffered.) | 1915 // (Probably want the channel to be buffered.) |
1915 type Chan chan *http.Request | 1916 type Chan chan *http.Request |
1916 | 1917 |
1917 func (ch Chan) ServeHTTP(c http.ResponseWriter, req *http.Request) { | 1918 func (ch Chan) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
1918 ch <- req | 1919 ch <- req |
1919 fmt.Fprint(c, "notification sent") | 1920 fmt.Fprint(w, "notification sent") |
1920 } | 1921 } |
1921 </pre> | 1922 </pre> |
1922 <p> | 1923 <p> |
1923 Finally, let's say we wanted to present on <code>/args</code> the arguments | 1924 Finally, let's say we wanted to present on <code>/args</code> the arguments |
1924 used when invoking the server binary. | 1925 used when invoking the server binary. |
1925 It's easy to write a function to print the arguments. | 1926 It's easy to write a function to print the arguments. |
1926 </p> | 1927 </p> |
1927 <pre> | 1928 <pre> |
1928 func ArgServer() { | 1929 func ArgServer() { |
1929 for i, s := range os.Args { | 1930 for i, s := range os.Args { |
1930 fmt.Println(s) | 1931 fmt.Println(s) |
1931 } | 1932 } |
1932 } | 1933 } |
1933 </pre> | 1934 </pre> |
1934 <p> | 1935 <p> |
1935 How do we turn that into an HTTP server? We could make <code>ArgServer</code> | 1936 How do we turn that into an HTTP server? We could make <code>ArgServer</code> |
1936 a method of some type whose value we ignore, but there's a cleaner way. | 1937 a method of some type whose value we ignore, but there's a cleaner way. |
1937 Since we can define a method for any type except pointers and interfaces, | 1938 Since we can define a method for any type except pointers and interfaces, |
1938 we can write a method for a function. | 1939 we can write a method for a function. |
1939 The <code>http</code> package contains this code: | 1940 The <code>http</code> package contains this code: |
1940 </p> | 1941 </p> |
1941 <pre> | 1942 <pre> |
1942 // The HandlerFunc type is an adapter to allow the use of | 1943 // The HandlerFunc type is an adapter to allow the use of |
1943 // ordinary functions as HTTP handlers. If f is a function | 1944 // ordinary functions as HTTP handlers. If f is a function |
1944 // with the appropriate signature, HandlerFunc(f) is a | 1945 // with the appropriate signature, HandlerFunc(f) is a |
1945 // Handler object that calls f. | 1946 // Handler object that calls f. |
1946 type HandlerFunc func(ResponseWriter, *Request) | 1947 type HandlerFunc func(ResponseWriter, *Request) |
1947 | 1948 |
1948 // ServeHTTP calls f(c, req). | 1949 // ServeHTTP calls f(c, req). |
1949 func (f HandlerFunc) ServeHTTP(c ResponseWriter, req *Request) { | 1950 func (f HandlerFunc) ServeHTTP(w ResponseWriter, req *Request) { |
1950 f(c, req) | 1951 f(w, req) |
1951 } | 1952 } |
1952 </pre> | 1953 </pre> |
1953 <p> | 1954 <p> |
1954 <code>HandlerFunc</code> is a type with a method, <code>ServeHTTP</code>, | 1955 <code>HandlerFunc</code> is a type with a method, <code>ServeHTTP</code>, |
1955 so values of that type can serve HTTP requests. Look at the implementation | 1956 so values of that type can serve HTTP requests. Look at the implementation |
1956 of the method: the receiver is a function, <code>f</code>, and the method | 1957 of the method: the receiver is a function, <code>f</code>, and the method |
1957 calls <code>f</code>. That may seem odd but it's not that different from, say, | 1958 calls <code>f</code>. That may seem odd but it's not that different from, say, |
1958 the receiver being a channel and the method sending on the channel. | 1959 the receiver being a channel and the method sending on the channel. |
1959 </p> | 1960 </p> |
1960 <p> | 1961 <p> |
1961 To make <code>ArgServer</code> into an HTTP server, we first modify it | 1962 To make <code>ArgServer</code> into an HTTP server, we first modify it |
1962 to have the right signature. | 1963 to have the right signature. |
1963 </p> | 1964 </p> |
1964 <pre> | 1965 <pre> |
1965 // Argument server. | 1966 // Argument server. |
1966 func ArgServer(c http.ResponseWriter, req *http.Request) { | 1967 func ArgServer(w http.ResponseWriter, req *http.Request) { |
1967 for i, s := range os.Args { | 1968 for i, s := range os.Args { |
1968 fmt.Fprintln(c, s) | 1969 fmt.Fprintln(w, s) |
1969 } | 1970 } |
1970 } | 1971 } |
1971 </pre> | 1972 </pre> |
1972 <p> | 1973 <p> |
1973 <code>ArgServer</code> now has same signature as <code>HandlerFunc</code>, | 1974 <code>ArgServer</code> now has same signature as <code>HandlerFunc</code>, |
1974 so it can be converted to that type to access its methods, | 1975 so it can be converted to that type to access its methods, |
1975 just as we converted <code>Sequence</code> to <code>IntArray</code> | 1976 just as we converted <code>Sequence</code> to <code>IntArray</code> |
1976 to access <code>IntArray.Sort</code>. | 1977 to access <code>IntArray.Sort</code>. |
1977 The code to set it up is concise: | 1978 The code to set it up is concise: |
1978 </p> | 1979 </p> |
(...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2795 | 2796 |
2796 func main() { | 2797 func main() { |
2797 flag.Parse() | 2798 flag.Parse() |
2798 http.Handle("/", http.HandlerFunc(QR)) | 2799 http.Handle("/", http.HandlerFunc(QR)) |
2799 err := http.ListenAndServe(*addr, nil) | 2800 err := http.ListenAndServe(*addr, nil) |
2800 if err != nil { | 2801 if err != nil { |
2801 log.Exit("ListenAndServe:", err) | 2802 log.Exit("ListenAndServe:", err) |
2802 } | 2803 } |
2803 } | 2804 } |
2804 | 2805 |
2805 func QR(c http.ResponseWriter, req *http.Request) { | 2806 func QR(w http.ResponseWriter, req *http.Request) { |
2806 templ.Execute(req.FormValue("s"), c) | 2807 templ.Execute(req.FormValue("s"), w) |
2807 } | 2808 } |
2808 | 2809 |
2809 func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) { | 2810 func UrlHtmlFormatter(w io.Writer, v interface{}, fmt string) { |
2810 template.HTMLEscape(w, []byte(http.URLEscape(v.(string)))) | 2811 template.HTMLEscape(w, []byte(http.URLEscape(v.(string)))) |
2811 } | 2812 } |
2812 | 2813 |
2813 | 2814 |
2814 const templateStr = ` | 2815 const templateStr = ` |
2815 <html> | 2816 <html> |
2816 <head> | 2817 <head> |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2889 <pre> | 2890 <pre> |
2890 verifying implementation | 2891 verifying implementation |
2891 type Color uint32 | 2892 type Color uint32 |
2892 ···· | 2893 ···· |
2893 // Check that Color implements image.Color and image.Image | 2894 // Check that Color implements image.Color and image.Image |
2894 var _ image.Color = Black | 2895 var _ image.Color = Black |
2895 var _ image.Image = Black | 2896 var _ image.Image = Black |
2896 </pre> | 2897 </pre> |
2897 --> | 2898 --> |
2898 | 2899 |
LEFT | RIGHT |