0% found this document useful (0 votes)
4 views

COMP3007_Modern_Programming_Languages (8)

This document outlines the key concepts of the Go programming language, focusing on blocks, variable shadowing, control structures, and functions. It explains the types of blocks, their scope rules, and best practices to avoid shadowing issues. Additionally, it covers control structures such as if statements, for loops, and switch statements, along with the cautious use of goto statements.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

COMP3007_Modern_Programming_Languages (8)

This document outlines the key concepts of the Go programming language, focusing on blocks, variable shadowing, control structures, and functions. It explains the types of blocks, their scope rules, and best practices to avoid shadowing issues. Additionally, it covers control structures such as if statements, for loops, and switch statements, along with the cautious use of goto statements.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

COMP3007 - Modern Programming Languages

Week 10: Go - Blocks, Shadowing, Control Structures and Functions

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel

Department of Computer Engineering

Fall 2024-2025

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 1 / 36
Outline

1 Introduction to Go Blocks and Scope

2 Variable Shadowing

3 Control Structures

4 Functions in Go

5 Best Practices

6 Conclusion

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 2 / 36
What are Blocks in Go?

A block is a sequence of declarations and statements within matching


braces
Every Go program has at least one block (the package block)
Blocks can be nested within other blocks
Different types of blocks: universe, package, file, function, local

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 3 / 36
Types of Blocks

Universe block: contains all Go source code


Package block: contains all source code for a package
File block: contains source code in a single file
Function block: contains code within a function
Local block: any other explicitly declared block

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 4 / 36
Block Example

1 package main // Package block begins


2
3 import "fmt"
4
5 func main () { // Function block begins
6 x := 10
7

8 { // Local block begins


9 y := 20
10 fmt. Println (x, y) // Can access both x and y
11 } // Local block ends
12
13 // fmt. Println (y) // Would cause error - y not in
scope
14 fmt. Println (x) // x is still in scope
15 } // Function block ends

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 5 / 36
Block Scope Rules

Each block creates a new scope


Inner blocks can access variables from outer blocks
Outer blocks cannot access variables from inner blocks
Variables declared in a block are only visible within that block
When a block ends, its local variables are destroyed

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 6 / 36
Implicit Blocks

1 if x := 42; x > 0 { // Implicit block begins


2 // x is visible here
3 fmt. Println (x)
4 } // Implicit block ends
5 // x is not visible here
6
7 for i := 0; i < 5; i++ { // Implicit block
8 // i is only visible in the loop
9 }

Control structures create implicit blocks


Variables declared in condition statements have block scope
Common in if, for, and switch statements

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 7 / 36
Block Lexical Scoping

Go uses lexical scoping


Scope of a name is determined by its location in source code
Compiler can determine scope during compilation
Helps prevent naming conflicts
Makes code easier to understand and maintain

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 8 / 36
Understanding Lexical Scoping
1 func outer () func () int {
2 x := 1 // x is declared in outer function 's scope
3
4 inner := func () int {
5 // inner function can access x because of
6 // lexical scoping - it can "see" variables
7 // in the scope where it was defined
8 x = x + 1
9 return x
10 }
11
12 return inner
13 }
14
15 func main () {
16 f := outer ()
17 fmt.Println(f()) // Prints: 2
18 fmt.Println(f()) // Prints: 3
19
20 // Each call to outer creates a new scope
21 g := outer ()
22 fmt.Println(g()) // Prints: 2
23 fmt.Println(f()) // Prints: 4
24 }

Variable x remains accessible to inner function


Each call to outer creates a new lexical environment
f and g have their own independent copies of x
Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department
COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 9 / 36
What is Variable Shadowing?

Occurs when a variable in an inner scope has the same name as a


variable in an outer scope
The inner variable ”shadows” the outer variable
The outer variable becomes temporarily inaccessible
A common source of bugs if not used carefully

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 10 / 36
Basic Shadowing Example

1 func main () {
2 x := 10
3 fmt. Println (x) // Prints 10
4
5 {
6 x := 20 // New variable shadows outer x
7 fmt. Println (x) // Prints 20
8 }
9
10 fmt. Println (x) // Prints 10 - original x
11 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 11 / 36
Function Parameter Shadowing

1 var x = 10 // Package level variable


2
3 func printValue (x int) { // x shadows package x
4 fmt. Println (x) // Refers to parameter x
5 }
6
7 func main () {
8 fmt. Println (x) // Prints 10
9 printValue (20) // Prints 20
10 fmt. Println (x) // Prints 10
11 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 12 / 36
Common Shadowing Scenarios

Loop variables shadowing outer variables


Function parameters shadowing global variables
Variables in if/switch statements shadowing outer variables
Method receivers shadowing package variables
Import aliases shadowing local names

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 13 / 36
Loop Variable Shadowing

1 func main () {
2 x := 10
3 vals := [] int {1, 2, 3}
4
5 for _, x := range vals { // x shadows outer x
6 fmt. Println (x) // Prints values from vals
7 }
8
9 fmt. Println (x) // Prints 10 - original x
10 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 14 / 36
Best Practices with Shadowing

Avoid shadowing when possible


Use different variable names to prevent confusion
Be especially careful with package-level variables
Use tools like go vet to detect shadowing
Document intentional shadowing clearly

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 15 / 36
Detecting Shadowing

1 package main
2
3 var err error // Package level error
4
5 func process () error {
6 if someCondition {
7 if err := something (); err != nil {
8 // err shadows package err
9 return err
10 }
11 }
12 return err // Which err is this?
13 }

This is a common source of bugs


The inner err shadows the outer one
Can lead to returning wrong error value
Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department
COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 16 / 36
Universal Block in Go

The universe block is the outermost block in Go


Contains all predeclared identifiers:
Built-in types: bool, int, string, etc.
Constants: true, false, iota
Zero value: nil
Built-in functions: make, len, cap, new, etc.
These identifiers are available everywhere in Go code
Cannot be redeclared in other blocks (will cause compilation error)
Forms the foundation of Go’s type system and basic operations

1 // These would cause compilation errors :


2 func make () {} // Cannot redefine 'make '
3 const true = false // Cannot redefine 'true '
4 type int struct {} // Cannot redefine 'int '

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 17 / 36
If Statements in Go

No parentheses needed around conditions


Braces are mandatory
Can include initialization statement
Variables declared in init are only visible in if scope
1 // Basic if
2 if x > 0 {
3 fmt.Println("Positive")
4 }
5
6 // If with initialization
7 if n := getValue (); n < 0 {
8 fmt.Println("Negative")
9 } else if n == 0 {
10 fmt.Println("Zero")
11 } else {
12 fmt.Println("Positive")
13 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 18 / 36
For Loop - Four Forms

1 // 1. Classic C-style
2 for i := 0; i < 10; i++ {
3 fmt.Println(i)
4 }
5
6 // 2. Condition -only (like while)
7 count := 0
8 for count < 5 {
9 count ++
10 }
11
12 // 3. Infinite loop
13 for {
14 // Do something forever
15 break // Exit condition
16 }
17
18 // 4. Range -based
19 nums := [] int{1, 2, 3}
20 for index , value := range nums {
21 fmt.Printf("Index: %d, Value: %d\n", index , value)
22 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 19 / 36
Iterating Over Maps and Strings

1 // Map iteration
2 colors := map[string]string{
3 "red": "#ff0000",
4 "green": "#00 ff00",
5 }
6 for key , value := range colors {
7 fmt.Printf("Key: %s, Value: %s\n", key , value)
8 }
9
10 // String iteration (by rune)
11 str := "Hello , ��"
12 for i, char := range str {
13 fmt.Printf("position %d: %c\n", i, char)
14 }
15
16 // String iteration (by byte)
17 for i := 0; i < len(str); i++ {
18 fmt.Printf("byte at %d: %x\n", i, str[i])
19 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 20 / 36
Switch Statements

1 // Basic switch
2 switch day := time.Now().Weekday (); day {
3 case time.Saturday , time.Sunday:
4 fmt.Println("Weekend")
5 default :
6 fmt.Println("Weekday")
7 }
8
9 // Switch without expression (like if -else)
10 switch {
11 case hour < 12:
12 fmt.Println("Morning")
13 case hour < 17:
14 fmt.Println("Afternoon")
15 default :
16 fmt.Println("Evening")
17 }
18
19 // Type switch
20 var i interface {} = "hello"
21 switch v := i.( type) {
22 case int:
23 fmt.Printf("Integer: %v\n", v)
24 case string:
25 fmt.Printf("String: %v\n", v)
26 default :
27 fmt.Printf("Unknown type\n")
28 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 21 / 36
Labels and Break/Continue

1 OuterLoop:
2 for i := 0; i < 5; i++ {
3 for j := 0; j < 5; j++ {
4 if i*j == 6 {
5 break OuterLoop // Breaks out of both loops
6 }
7 if j == 2 {
8 continue OuterLoop // Continues outer loop
9 }
10 }
11 }
12
13 // Break with label in switch
14 FindValue:
15 switch n := getValue (); n {
16 case 1:
17 if someCondition {
18 break FindValue
19 }
20 fmt.Println("One")
21 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 22 / 36
Goto Statement - Use with Caution
Go supports goto but it should be used sparingly
Common legitimate uses:
Error handling in complex functions
Breaking out of nested loops
Implementing state machines
Restrictions:
Cannot jump over variable declarations
Cannot jump into different function
Cannot jump into block scopes
1 func processWithError () error {
2 if err := step1 (); err != nil {
3 goto handleError
4 }
5 if err := step2 (); err != nil {
6 goto handleError
7 }
8 return nil
9
10 handleError:
11 cleanup ()
12 return err
13 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 23 / 36
Control Structure Best Practices

Keep nesting levels minimal


Prefer early returns over deep nesting
Use switch over long if-else chains
Consider readability when using labels
Avoid goto except for specific use cases
Use range when iterating over collections
Handle all cases in switch statements
Consider default cases for switches

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 24 / 36
Function Basics in Go

Functions are first-class citizens in Go


Can be assigned to variables
Can be passed as parameters
Can be returned from other functions
Support multiple return values
Can have named return values
Are always pass-by-value

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 25 / 36
Declaring and Calling Functions

1 // Basic function declaration


2 func add(x int , y int) int {
3 return x + y
4 }
5
6 // Shortened parameter type declaration
7 func subtract(x, y int) int {
8 return x - y
9 }
10
11 // Function with no return value
12 func printSum(x, y int) {
13 fmt.Println(x + y)
14 }
15
16 func main () {
17 result := add(5, 3) // Call with positional arguments
18 printSum (10, 20) // Function with no return value
19 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 26 / 36
Simulating Named and Optional Parameters
1 // Using struct to simulate named parameters
2 type Options struct {
3 FirstName string
4 LastName string
5 Age int
6 Email *string // Optional field
7 }
8
9 func CreateUser(opts Options) User {
10 // Default value for optional Email
11 email := "[email protected]"
12 if opts.Email != nil {
13 email = *opts.Email
14 }
15
16 return User{
17 Name: opts.FirstName + " " + opts.LastName ,
18 Age: opts.Age ,
19 Email: email ,
20 }
21 }
22
23 // Usage
24 myEmail := "[email protected]"
25 user := CreateUser(Options{
26 FirstName: "John",
27 LastName: "Doe",
28 Age: 30,
29 Email: &myEmail ,
30 })

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 27 / 36
Variadic Input Parameters and Slices

1 // Variadic function
2 func sum(nums ... int) int {
3 total := 0
4 for _, num := range nums {
5 total += num
6 }
7 return total
8 }
9
10 // Using slices with variadic functions
11 func main () {
12 // Direct variadic calls
13 fmt.Println(sum(1, 2, 3))
14
15 // Passing a slice
16 numbers := [] int{1, 2, 3, 4}
17 fmt.Println(sum(numbers ...))
18 }
19
20 // Mixing regular and variadic parameters
21 func printNameAndNumbers(name string , nums ... int) {
22 fmt.Printf("%s: ", name)
23 for _, num := range nums {
24 fmt.Printf("%d ", num)
25 }
26 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 28 / 36
Multiple Return Values
1 // Multiple return values
2 func divide(x, y float64 ) (float64 , error) {
3 if y == 0 {
4 return 0, errors.New("division by zero")
5 }
6 return x / y, nil
7 }
8
9 // Multiple value assignment
10 func minMax(nums [] int) (min int , max int) {
11 if len(nums) == 0 {
12 return 0, 0
13 }
14 min , max = nums [0], nums [0]
15 for _, num := range nums [1:] {
16 if num < min {
17 min = num
18 }
19 if num > max {
20 max = num
21 }
22 }
23 return
24 }
25
26 func main () {
27 result , err := divide (10, 2)
28 if err != nil {
29 fmt.Println("Error:", err)
30 return
31 }
32 fmt.Println("Result:", result)
33
Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department
COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 29 / 36
Named Return Values

1 // Named return values


2 func split(sum int) (x, y int) {
3 x = sum * 4 / 9
4 y = sum - x
5 return // Naked return
6 }
7
8 // Better practice with explicit returns
9 func calculate(radius float64 ) (area , circumference float64 ) {
10 area = math.Pi * radius * radius
11 circumference = 2 * math.Pi * radius
12 return area , circumference // Explicit return
13 }

Named returns can improve readability


Variables are initialized to zero values
Naked returns should be used sparingly
Better to be explicit with returns in longer functions

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 30 / 36
Functions as Values

1 // Function type declaration


2 type Operation func(x, y int) int
3
4 // Function as variable
5 func main () {
6 var op Operation = func(x, y int) int {
7 return x + y
8 }
9
10 result := op(5, 3)
11
12 // Function map
13 operations := map[string]Operation{
14 "add": func(x, y int) int { return x + y },
15 "subtract": func(x, y int) int { return x - y },
16 }
17
18 result = operations["add"](10, 5)
19 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 31 / 36
Closures and Anonymous Functions

1 func makeCounter () func () int {


2 count := 0
3 return func () int {
4 count ++
5 return count
6 }
7 }
8
9 func main () {
10 counter1 := makeCounter ()
11 fmt.Println(counter1 ()) // 1
12 fmt.Println(counter1 ()) // 2
13
14 counter2 := makeCounter ()
15 fmt.Println(counter2 ()) // 1
16
17 // Anonymous function with immediate execution
18 func(x int) {
19 fmt.Printf("Anonymous func: %d\n", x)
20 }(42)
21 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 32 / 36
defer Statement
1 func processFile(filename string) error {
2 f, err := os.Open(filename)
3 if err != nil {
4 return err
5 }
6 defer f.Close () // Will be called when function returns
7
8 // Process file ...
9 return nil
10 }
11
12 // Multiple defers (LIFO order)
13 func multipleDefers () {
14 fmt.Println("start")
15 defer fmt.Println("1")
16 defer fmt.Println("2")
17 defer fmt.Println("3")
18 fmt.Println("end")
19 }
20 // Prints: start , end , 3, 2, 1

defer delays execution until surrounding function returns


Useful for cleanup operations
Arguments are evaluated immediately
Multiple defers execute in LIFO order
Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department
COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 33 / 36
Call By Value in Go

Go is strictly pass by value


Even pointers are passed by value
Each function gets its own copy of arguments
To modify original values:
Use pointers as parameters
Return new values
Use pointer receivers in methods
Slices and maps contain internal pointers
Understanding this is crucial for performance

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 34 / 36
Conclusion

Understanding blocks and scope is fundamental to Go programming


Proper use of control structures leads to cleaner code
Functions are first-class citizens in Go
Best practices help write maintainable Go code

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 35 / 36
Thank You! Any Questions?

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 36 / 36

You might also like