like Python. a = " h e l l o " b = 1 # b u t a l s o a = 2 Static typing - can be verbose, like Java or C++. F o o f o o = n e w F o o ( ) ; Static typing with inferred types, like Go. a : = " h e l l o " b : = 1 / / b u t n o a = 2 Statically-typed Python? Check mypy (http://www.mypy-lang.org/) and Cython (http://cython.org/) .
y t h o n i s t a ' # T h i s c o d e o n l y w o r k s h a l f o f t h e t i m e . i f r a n d o m . r a n d o m ( ) > 0 . 5 : p r i n t ' h e y ' + n a m e + ' , y o u w i n ! ' e l s e : p r i n t ' s o r r y ' + n a n e + ' , y o u l o s e ' I don't want start a flame war here but ... 100% code coverage is a symptom Code coverage should point you to untested cases. Not a way to find typos! 100% code coverage doesn't mean bug free.
- "not too slow" is often not fast enough. Magic! (e.g.: _ _ m a g i c _ _ : * * k a r g s , _ _ g e t a t t r _ _ ) A list of magic methods in Python: www.rafekettler.com/magicmethods.html (http://www.rafekettler.com/magicmethods.html)
and the Zen of Python (http://talks.golang.org/2012/zen.slide#1) ) Hashes and arrays are part of the language. The standard library. Magic! A bit of code can do a lot.
f i b ( n ) : a , b = 0 , 1 f o r i i n r a n g e ( n ) : a , b = b , a + b r e t u r n b d e f f i b _ r e c ( n ) : i f n < = 1 : r e t u r n 1 e l s e : r e t u r n f i b _ r e c ( n - 1 ) + f i b _ r e c ( n - 2 ) f o r x i n r a n g e ( 1 0 ) : p r i n t f i b ( x ) , f i b _ r e c ( x )
( n i n t ) i n t { a , b : = 0 , 1 f o r i : = 0 ; i < n ; i + + { a , b = b , a + b } r e t u r n b } f u n c f i b R e c ( n i n t ) i n t { i f n < = 1 { r e t u r n 1 } r e t u r n f i b R e c ( n - 1 ) + f i b R e c ( n - 2 ) } f u n c m a i n ( ) { f o r i : = 0 ; i < 1 0 ; i + + { f m t . P r i n t l n ( f i b ( i ) , f i b R e c ( i ) ) } } Run
f f i b ( n ) : a , b = 0 , 1 f o r i i n r a n g e ( n ) : a , b = b , a + b y i e l d a Mechanically complex. f = f i b ( 1 0 ) t r y : w h i l e T r u e : p r i n t f . n e x t ( ) e x c e p t S t o p I t e r a t i o n : p r i n t ' d o n e ' But very easy to use. f o r x i n f i b ( 1 0 ) : p r i n t x p r i n t ' d o n e '
e l d . f u n c f i b ( c c h a n i n t , n i n t ) { a , b : = 0 , 1 f o r i : = 0 ; i < n ; i + + { a , b = b , a + b c < - a } c l o s e ( c ) } f u n c m a i n ( ) { c : = m a k e ( c h a n i n t ) g o f i b ( c , 1 0 ) f o r x : = r a n g e c { f m t . P r i n t l n ( x ) } } Run
f i b ( n i n t ) c h a n i n t { c : = m a k e ( c h a n i n t ) g o f u n c ( ) { a , b : = 0 , 1 f o r i : = 0 ; i < n ; i + + { a , b = b , a + b c < - a } c l o s e ( c ) } ( ) r e t u r n c } f u n c m a i n ( ) { f o r x : = r a n g e f i b ( 1 0 ) { f m t . P r i n t l n ( x ) } } Run
channel and sends the first n prime numbers on it. Given the function p r i m e : / / p r i m e r e t u r n s t r u e i f n i s a p r i m e n u m b e r . f u n c p r i m e ( n i n t ) b o o l { f o r i : = 2 ; i < n ; i + + { i f n % i = = 0 { r e t u r n f a l s e } } r e t u r n t r u e } Use the Go playground: golang.org/s/go4py-ex1 (http://golang.org/s/go4py-ex1)
i m e s ( n i n t ) c h a n i n t { c : = m a k e ( c h a n i n t ) g o f u n c ( ) { f o r i : = 1 ; n > 0 ; i + + { i f p r i m e ( i ) { c < - i n - - } } c l o s e ( c ) } ( ) r e t u r n c } f u n c m a i n ( ) { f o r p : = r a n g e p r i m e s ( 1 0 ) { f m t . P r i n t l n ( p ) } } Run
r P r i m e s function that takes a channel of ints as a parameter and returns another channel of ints. All the prime numbers that f i l t e r P r i m e s receives from the input channel are sent into the output channel. Complete this code snippet: golang.org/s/go4py-ex2 (http://golang.org/s/go4py-ex2)
t e r P r i m e s ( c i n c h a n i n t ) c h a n i n t { c o u t : = m a k e ( c h a n i n t ) g o f u n c ( ) { f o r v : = r a n g e c i n { i f p r i m e ( v ) { c o u t < - v } } c l o s e ( c o u t ) } ( ) r e t u r n c o u t } f u n c m a i n ( ) { f o r p : = r a n g e f i l t e r P r i m e s ( f i b ( 2 0 ) ) { f m t . P r i n t l n ( p ) } } Run
generators. They can be used to model all kinds of concurrent systems. To learn more: Concurrency patterns (http://talks.golang.org/2012/concurrency.slide#1) , by Rob Pike Advanced Concurrency Patterns (http://talks.golang.org/2013/advconc.slide#1) , by Sameer Ajmani
a m e s t r u c t { F i r s t s t r i n g M i d d l e s t r i n g L a s t s t r i n g } A method declaration. f u n c ( n N a m e ) S t r i n g ( ) s t r i n g { r e t u r n f m t . S p r i n t f ( " % s % c . % s " , n . F i r s t , n . M i d d l e [ 0 ] , s t r i n g s . T o U p p e r ( n . L a s t ) ) } Constructing a N a m e and using it. n : = N a m e { " W i l l i a m " , " M i k e " , " S m i t h " } f m t . P r i n t f ( " % s " , n . S t r i n g ( ) ) Run
y p e S i m p l e N a m e s t r i n g You can define methods on any type. f u n c ( s S i m p l e N a m e ) S t r i n g ( ) s t r i n g { r e t u r n s t r i n g ( s ) } Or almost any type. f u n c ( s s t r i n g ) N o W a y ( ) You can only define methods on types within the same package.
m t package: t y p e S t r i n g e r i n t e r f a c e { S t r i n g ( ) s t r i n g } f m t . P r i n t l n calls the String method if the parameter is a S t r i n g e r . A type with all the methods of the interface implements the interface. Implicit satisfaction == No "implements" Structural typing: it doesn't just sound like a duck, it is a duck. And that's checked at compile time. n = N a m e { " W i l l i a m " , " M i k e " , " S m i t h " } f m t . P r i n t l n ( n ) Run
f a u t h _ r e q u i r e d ( m y f u n c ) : d e f c h e c k u s e r ( s e l f ) : u s e r = p a r s e _ q s ( u r l p a r s e ( s e l f . p a t h ) . q u e r y ) . g e t ( ' u s e r ' ) i f u s e r : s e l f . u s e r = u s e r [ 0 ] m y f u n c ( s e l f ) e l s e : s e l f . w f i l e . w r i t e ( ' u n k n o w n u s e r ' ) r e t u r n c h e c k u s e r A function can be decorated using @ . c l a s s m y H a n d l e r ( B a s e H T T P R e q u e s t H a n d l e r ) : @ a u t h _ r e q u i r e d d e f d o _ G E T ( s e l f ) : s e l f . w f i l e . w r i t e ( ' H e l l o , % s ! ' % s e l f . u s e r )
e r v e r = H T T P S e r v e r ( ( ' ' , P O R T _ N U M B E R ) , m y H a n d l e r ) s e r v e r . s e r v e _ f o r e v e r ( ) e x c e p t K e y b o a r d I n t e r r u p t : s e r v e r . s o c k e t . c l o s e ( ) This is unauthorized: localhost:8080/hi (http://localhost:8080/hi) This is authorized: localhost:8080/hi?user=john (http://localhost:8080/hi?user=john)
provide decorators in the language, but its function literal syntax and simple scoping rules make it easy to do something similar. v a r h i H a n d l e r = a u t h R e q u i r e d ( f u n c ( w h t t p . R e s p o n s e W r i t e r , r * h t t p . R e q u e s t ) { f m t . F p r i n t f ( w , " H i , % v " , r . F o r m V a l u e ( " u s e r " ) ) } , ) A wrapper function. f u n c a u t h R e q u i r e d ( f h t t p . H a n d l e r F u n c ) h t t p . H a n d l e r F u n c { r e t u r n f u n c ( w h t t p . R e s p o n s e W r i t e r , r * h t t p . R e q u e s t ) { i f r . F o r m V a l u e ( " u s e r " ) = = " " { h t t p . E r r o r ( w , " u n k n o w n u s e r " , h t t p . S t a t u s F o r b i d d e n ) r e t u r n } f ( w , r ) } }
authorized: localhost:8080/hi?user=john (http://localhost:8080/hi?user=john) f u n c m a i n ( ) { h t t p . H a n d l e F u n c ( " / h i " , h i H a n d l e r ) h t t p . L i s t e n A n d S e r v e ( " : 8 0 8 0 " , n i l ) } Run
errors to indicate that something bad happened. The n e t / h t t p package from the standard library defines the type H a n d l e r F u n c . t y p e H a n d l e r F u n c f u n c ( R e s p o n s e W r i t e r , * R e q u e s t ) But it's often useful to unify the error handling into a single function to avoid repetition. t y p e e r r o r H a n d l e r f u n c ( h t t p . R e s p o n s e W r i t e r , * h t t p . R e q u e s t ) e r r o r Write a decorator that given a e r r o r H a n d l e r returns a h t t p . H a n d l e r F u n c . If an error occurs it logs it and returns an http error page.
a n d l e r . f u n c h a n d l e r ( w h t t p . R e s p o n s e W r i t e r , r * h t t p . R e q u e s t ) e r r o r { n a m e : = r . F o r m V a l u e ( " n a m e " ) i f n a m e = = " " { r e t u r n f m t . E r r o r f ( " e m p t y n a m e " ) } f m t . F p r i n t l n ( w , " H i , " , n a m e ) r e t u r n n i l } We want to use it as follows. h t t p . H a n d l e F u n c ( " / h i " , h a n d l e E r r o r ( h a n d l e r ) ) Implement h a n d l e E r r o r using the playground. golang.org/s/go4py-ex3 (http://golang.org/s/go4py-ex3)
a n d l e E r r o r ( f e r r o r H a n d l e r ) h t t p . H a n d l e r F u n c { r e t u r n f u n c ( w h t t p . R e s p o n s e W r i t e r , r * h t t p . R e q u e s t ) { e r r : = f ( w , r ) i f e r r ! = n i l { l o g . P r i n t f ( " % v " , e r r ) h t t p . E r r o r ( w , " O o p s ! " , h t t p . S t a t u s I n t e r n a l S e r v e r E r r o r ) } } } / / F a k e r e q u e s t w i t h o u t ' n a m e ' p a r a m e t e r . r : = & h t t p . R e q u e s t { } w : = n e w D u m m y R e s p ( ) h a n d l e E r r o r ( h a n d l e r ) ( w , r ) f m t . P r i n t l n ( " r e s p a : " , w ) / / F a k e r e q u e s t w i t h ' n a m e ' p a r a m e t e r ' j o h n ' . r . F o r m [ " n a m e " ] = [ ] s t r i n g { " j o h n " } w = n e w D u m m y R e s p ( ) h a n d l e E r r o r ( h a n d l e r ) ( w , r ) f m t . P r i n t l n ( " r e s p b : " , w ) Run
Often used for testing purposes. For example, say we want to test this function: d e f s a y _ h i ( u s r ) : i f a u t h ( u s r ) : p r i n t ' H i , % s ' % u s r e l s e : p r i n t ' u n k n o w n u s e r % s ' % u s r Which depends on a function that makes an HTTP request: d e f a u t h ( u s r ) : t r y : r = u r l l i b . u r l o p e n ( a u t h _ u r l + ' / ' + u s r ) r e t u r n r . g e t c o d e ( ) = = 2 0 0 e x c e p t : r e t u r n F a l s e
i without making HTTP requests by stubbing out a u t h : d e f s a y h i t e s t ( ) : # T e s t a u t h e n t i c a t e d u s e r g l o b a l s ( ) [ ' a u t h ' ] = l a m b d a x : T r u e s a y _ h i ( ' J o h n ' ) # T e s t u n a u t h e n t i c a t e d u s e r g l o b a l s ( ) [ ' a u t h ' ] = l a m b d a x : F a l s e s a y _ h i ( ' J o h n ' )
f u n c s a y H i ( u s e r s t r i n g ) { i f ! a u t h ( u s e r ) { f m t . P r i n t f ( " u n k n o w n u s e r % v \ n " , u s e r ) r e t u r n } f m t . P r i n t f ( " H i , % v \ n " , u s e r ) } Which depends on v a r a u t h = f u n c ( u s e r s t r i n g ) b o o l { r e s , e r r : = h t t p . G e t ( a u t h U R L + " / " + u s e r ) r e t u r n e r r = = n i l & & r e s . S t a t u s C o d e = = h t t p . S t a t u s O K }
auth easily. f u n c T e s t S a y H i ( ) { a u t h = f u n c ( s t r i n g ) b o o l { r e t u r n t r u e } s a y H i ( " J o h n " ) a u t h = f u n c ( s t r i n g ) b o o l { r e t u r n f a l s e } s a y H i ( " J o h n " ) } Run