Go: ООП

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 23 фев 2024, 19:32

Olej писал(а):
23 фев 2024, 08:36
Нужны хорошие идеи по ООП
А ещё одна хорошая идея :-D ... В стандартной библиотеке GoLang (https://pkg.go.dev/std@go1.22.0) есть такая группа пакетов как container (container) а в ней 3 таих пакета для import:
1). heap - Package heap provides heap operations for any type that implements heap.Interface.
2). list - Package list implements a doubly linked list.
3). ring - Package ring implements operations on circular lists.

И вот п.3 особенно интересен (мне), потому что это тот кольцевой двусвязный список, на котором именно построены большинство динамических структур ядра Linux :!: :!: :!:
И на котором дальше можно строить всё что вздумается в динамике: деревья, сбалансированные деревья, красно-чёрные списки ... и всё-всё-всё...
А во-вторых, потому что с таким списком кольцевым нельзя никогда слететь в SIGSEGV - потому что в нём нет концевых веток nil.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 23 фев 2024, 19:50

Olej писал(а):
23 фев 2024, 19:20
Встраивание и агрегирование
Olej писал(а):
23 фев 2024, 19:32
есть такая группа пакетов как container (container)
Вот первое объеденить со вторым... :lol:

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 23 фев 2024, 20:17

Olej писал(а):
23 фев 2024, 19:50
Вот первое объеденить со вторым...

Код: Выделить всё

package main

import (
	"fmt"
   "container/ring" 
   "github.com/eiannone/keyboard"   
	"unicode"
   C "image/color"
)
/*  type RGBA struct {
 *	   R, G, B, A uint8
 *  }
 */

type point struct {
	x, y float32
}

type pixel struct {
   point
   C.RGBA
}

func px(x, y float32, r, g, b, a uint8) pixel {
   return pixel{point{x, y}, C.RGBA{r, g, b, a}}
}

func (p pixel) String() string { // формат вывода
	return fmt.Sprintf("[%5.2f,%5.2f]{%03v,%03v,%03v,%03v}", 
                      p.x, p.y, p.R, p.G, p.B, p.A)
}

type shape []pixel

func main() {
   s := shape { px( 2,  0, 255,   0,   0, 255),
                px( 0,  2, 127, 127,   0, 255),
                px(-2,  0,   0, 255,   0, 255),
                px( 0, -2,   0, 127, 127, 255),
              }
   for i, x := range s { fmt.Printf("%d -> %v\n", i, x) }
   var r *ring.Ring
   for i, z := range s {
      x := ring.New(1)
      x.Value = z
      if i == 0 {
         r = x
      } else {
         y := r.Link(x)
         r = y
      }
   }
   show := func() {
   	// Iterate through the combined ring and print its contents
   	r.Do(func(p any) { fmt.Print(p.(pixel), " ") }) 
      println()
   }
   show()

   keyboard.Open()                  // неблокирующий ввод с клавиатуры
   defer keyboard.Close()
   chChan := make(chan rune)        // канал ввода с клавиатуры
   go func(chChan chan <- rune) {   // горутина ввода клавиши
      for {
         ch, _, _ := keyboard.GetKey()
         chChan <- ch
      }
   }(chChan)


   for {
      ch := <- chChan              // вводимые символы
      if ch == 0 { 
         break 
      } else if unicode.IsControl(ch) {
         break 
      } else if unicode.IsLetter(ch) {
         r = r.Next()         
      } else if unicode.IsDigit(ch) {
         r = r.Prev() 
      } else {
         break
      }
      show()
   }
   println()
}
Полезности и осмысленности в этом коде мало ... но зато много манипуляции с данными... :lol: ... и встраивание, и агрегирование ...
Вложения
ring.go
(2.02 КБ) 5 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 23 фев 2024, 21:11

Olej писал(а):
23 фев 2024, 19:50
Вот первое объеденить со вторым...
Там тип shape - 2D геометрическая фигура - это массив объектов типа pixel, в который ...
Olej писал(а):
23 фев 2024, 19:50
Встраивание и агрегирование
... агрегируются:
1). импортируемый тип color.RGBA ...
2). самописный тип point ... в который, в свою очередь, встраивается 2 float32 координаты: X и Y ...
Вот это для меня было 1-й задачей: начально инициализировать всю эту иерархию, начиная от type shape - фигуры ... что и делается:

Код: Выделить всё

s := shape { 
                px( 2,  0, 255,   0,   0, 255),
                px( 0,  2, 127, 127,   0, 255),
                px(-2,  0,   0, 255,   0, 255),
                px( 0, -2,   0, 127, 127, 255),
           }
Пока я как-то лучше не придумал...

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 23 фев 2024, 21:30

Olej писал(а):
23 фев 2024, 21:11
было 1-й задачей:
А 2-й задачей - затолкать поэлементно этот линейный массив pixel в циклический кольцевой список, импортируемый из container/ring ...
А 3-й задачей - небокирующий ввод с клавиатуры (нажатие клавиш), так чтобы:
- а при нажатии любой цифры олова циклического списка перескакивала Next()
- при нажатии любой цифры голова циклического списка перескакивала Prev()
- так ещё чтобы можно было по "нецензурным" клавишам (^D, Enter, Пробел, ...) - завершить программу нормально и возвратить клавиатуру в канонический построчный режим ввода ... иначе вкладке терминала, где это выполняете - хана :cry:
Ну и вот оно:

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/ring$ go run ring.go
0 -> [ 2.00, 0.00]{255,000,000,255}
1 -> [ 0.00, 2.00]{127,127,000,255}
2 -> [-2.00, 0.00]{000,255,000,255}
3 -> [ 0.00,-2.00]{000,127,127,255}
[ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255} [ 0.00,-2.00]{000,127,127,255}
[ 0.00,-2.00]{000,127,127,255} [ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255}
[ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255} [ 0.00,-2.00]{000,127,127,255}
[ 0.00,-2.00]{000,127,127,255} [ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255}
[ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255} [ 0.00,-2.00]{000,127,127,255}
[ 0.00,-2.00]{000,127,127,255} [ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255}
[ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255} [ 0.00,-2.00]{000,127,127,255}
[ 0.00,-2.00]{000,127,127,255} [ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255}
[ 2.00, 0.00]{255,000,000,255} [-2.00, 0.00]{000,255,000,255} [ 0.00, 2.00]{127,127,000,255} [ 0.00,-2.00]{000,127,127,255}

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 26 фев 2024, 00:13

Алгоритм Луна... :-o
Алгоритм Луна - это не про "американцы на Луне" ... куда они совсем недавно за последние 40 лет долетели :lol: а это - верификация номеров банковских карт (крутым кулцхакерам напрячься и приготовиться :lol: ): Алгоритм Луна:
Алгоритм Лу́на (англ. Luhn algorithm) — алгоритм вычисления контрольной цифры номера пластиковой карты в соответствии со стандартом ISO/IEC 7812. Не является криптографическим средством, а предназначен в первую очередь для выявления ошибок, вызванных непреднамеренным искажением данных (например, при ручном вводе номера карты, при приёме данных о номере социального страхования по телефону). Позволяет лишь с некоторой степенью достоверности судить об отсутствии ошибок в блоке цифр, но не даёт возможности нахождения и исправления обнаруженной неточности.

Алгоритм разработан сотрудником фирмы IBM Хансом Питером Луном, описан в США в 1954 году, патент получен в 1960 году.

В настоящее время алгоритм является публичным достоянием.
https://ru.wikipedia.org/wiki/Алгоритм_Луна
U.S. Patent 2 950 048 Computer for Verifying Numbers, Hans P. Luhn, August 23, 1960.
Наиболее распространённые применения
- Номера всех банковских карт
...
Как я понял, наблюдая цифры (см. дальше) это такой себе ... алгоритм хэширования 16-значного числа в 1-значное ... по представлению 50-х годов... , когда считали на счётах или на пальцах. :lol:
При таком "сжатии" - это фактически 1 проверочный разряд.
Но все банки используют для карт эту технику.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 26 фев 2024, 00:20

Olej писал(а):
26 фев 2024, 00:13
верификация номеров банковских карт

Код: Выделить всё

// https://ru.wikipedia.org/wiki/Алгоритм_Луна
// U.S. Patent 2 950 048 Computer for Verifying Numbers, Hans P. Luhn, August 23, 1960.

package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
)

const LEN = 16

type card struct {
	num [LEN]byte
}

func (c card) valid() (val bool, err error) {
	val = false
	err = nil
	var s byte = 0
	for i, d := range c.num {
		if !(d >= byte('0') && d <= byte('9')) {
			s := fmt.Sprintf("ошибка: не число!")
			err = errors.New(s)
			return
		} else {
			c.num[i] = c.num[i] - byte('0')
			if i%2 == 0 {
				c.num[i] = c.num[i] * 2
				if c.num[i] > 9 {
					c.num[i] -= 9
				}
			}
			s += c.num[i]
		}
	}
	return s % 10 == 0, nil
}

func (c card) String() string { // формат вывода
	s := ""
	for i := range LEN {
		s += string(c.num[i])
	}
	return s
}

func main() {
	for {
		crd, err := incard()
		if err == nil {
			v, err := crd.valid()
			if err != nil {
				fmt.Println(err)
				continue
			}
			fmt.Printf("номер %s : ", crd)			
			if v {
				fmt.Printf("верифицирован\n")
			} else {
				fmt.Printf("не верифицирован\n")
			}

		} else if err == io.EOF {
			break
		} else {
			fmt.Println(err)
			break
		}
	}
}

func incard() (*card, error) {
	scanner := bufio.NewScanner(os.Stdin)
	if !scanner.Scan() {
		return nil, io.EOF // ввод ^D - EOF
	}
	line1 := scanner.Text()
	if 0 == len(line1) {
		return nil, io.EOF // ввод Enter - пустая строка
	}
	line2 := ""
	for _, c := range line1 {
		if c != ' ' {
			line2 += string(c)
		}
	}
	if len(line2) != LEN {
		err := errors.New(fmt.Sprintf("длина %d должна быть %d",
			len(line2), LEN))
		return nil, err
	}
	crd := new(card)
	for i, c := range line2 {
		crd.num[i] = byte(c)
	}
	return crd, nil
}
Вложения
luna.go
(1.76 КБ) 5 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 26 фев 2024, 00:36

Olej писал(а):
26 фев 2024, 00:13
верификация номеров банковских карт

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ ./luna 
4561 2612 1234 5464
номер 4561261212345464 : не верифицирован
4561 2612 1234 5467
номер 4561261212345467 : верифицирован
5106 2110 7031 8501
номер 5106211070318501 : верифицирован
^C

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 5106 2110 7031 8501 | go run luna.go
номер 5106211070318501 : верифицирован

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 4561261212345467 | go run luna.go
номер 4561261212345467 : верифицирован

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 456126121234546 | go run luna.go
длина 15 должна быть 16

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 4561261212345461 | go run luna.go
номер 4561261212345461 : не верифицирован

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 45612612123454671 | go run luna.go
длина 17 должна быть 16

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 456126121234G467 | go run luna.go
ошибка: не число!

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo 456126121234Щ67 | go run luna.go
ошибка: не число!

Код: Выделить всё

olej@R420:~/2024/own.BOOKs/BHV.Go.3/examples.work/oop/luna$ echo "  4561 2612 1234 5467  " | ./luna
номер 4561261212345467 : верифицирован

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Go: ООП

Непрочитанное сообщение Olej » 26 фев 2024, 02:25

Olej писал(а):
23 фев 2024, 07:10
Let's Go: объектно-ориентированное программирование на Голанге
Философия дизайна Go

Корни Go основаны на C и, в более широком смысле, на семействе Algol. Кен Томпсон в шутку сказал, что Роб Пайк, Роберт Грейнджер и он сам собрались вместе и решили, что они ненавидят C ++. Будь то шутка или нет, Go сильно отличается от C ++. Подробнее об этом позже. Go - это предельная простота Это подробно объясняется Робом Пайком в Меньше в геометрической прогрессии.
Только точнее, наверное ... или то что ониимели в виду "на семействе Algol" - на Oberon, и, в обратной хронологии, Modula-2, Pascal...

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей