Так происходит потому, что в функцию в виде аргумента передается копия переменной, а не сама переменная, ибо x находится в пределах main().
А в случае с указателями, в виде аргумента функции передается адрес значения в памяти, что дает возможность функции “грубо” изменить значение по адресу в памяти.
Экономия памяти
Будь x примере выше типом данных посложнее, типа, структурой, массивом и т.д. — передача параметров по значению (с помощью переменной) было бы неэффективно из-за копирования значения и выделения под него памяти.
Переменные n и sep — это указатели на переменные-флаги, доступ к которым осуществляется косвенно с помощью *n и *sep.
flag.Parse() присваивает значение созданным переменным n и sep — только после этого можно использовать флаги в программе. flag.Parse() при ошибке выкидывает os.Exit(2).
Аргументы, не являющиеся флагами, доступны через flag.Args() как срез строк[]string.
new() function
Выражение new(T):
Создает неименованную переменную типа T
Инициализирует ее нулевым значением
Возвращает ее адрес
Проще говоря, new(T) создает указатель на нулевое значение указанного типа.
new() является просто синтаксическим удобством. Наглядно — две идентичные по поведению функции:
func newInt() *int { return new(int)}func newInt() *int { // Здесь уже приходится давать имя переменной var dummy int return &dummy}
new() для переменных структурных типов
В общем, new()используется относительно редко, ибо наиболее распространены неименованные переменные структурных типов, для которых есть более гибкий литеральный синтаксис.
Пример с указателями (ибо работа со структурами часто именно через них и выполняется):
pp := &Point{1, 2}
что эквивалентно:
pp := new(Point)*pp = Point{1, 2}
Соус: Книга Язык программирования Go→ Глава 4. Составные типы→ 4.4 Структуры→ 4.4.1 Структурные литералы
Соус: Книга Язык программирования Go→ Глава 2. Структура программы→ 2.3 Переменные→ 2.3.3 Функция new